mysqld.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:243k
- /* Copyright (C) 2000-2003 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- #include "mysql_priv.h"
- #include <m_ctype.h>
- #include <my_dir.h>
- #include "slave.h"
- #include "sql_repl.h"
- #include "repl_failsafe.h"
- #include "stacktrace.h"
- #include "mysqld_suffix.h"
- #ifdef HAVE_BERKELEY_DB
- #include "ha_berkeley.h"
- #endif
- #ifdef HAVE_INNOBASE_DB
- #include "ha_innodb.h"
- #endif
- #include "ha_myisam.h"
- #ifdef HAVE_ISAM
- #include "ha_isam.h"
- #endif
- #ifdef HAVE_NDBCLUSTER_DB
- #include "ha_ndbcluster.h"
- #endif
- #ifdef HAVE_INNOBASE_DB
- #define OPT_INNODB_DEFAULT 1
- #else
- #define OPT_INNODB_DEFAULT 0
- #endif
- #ifdef HAVE_BERKLEY_DB
- #define OPT_BDB_DEFAULT 1
- #else
- #define OPT_BDB_DEFAULT 0
- #endif
- #ifdef HAVE_ISAM_DB
- #define OPT_ISAM_DEFAULT 1
- #else
- #define OPT_ISAM_DEFAULT 0
- #endif
- #ifdef HAVE_NDBCLUSTER_DB
- #define OPT_NDBCLUSTER_DEFAULT 0
- #if defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
- #define OPT_NDB_SHM_DEFAULT 1
- #else
- #define OPT_NDB_SHM_DEFAULT 0
- #endif
- #else
- #define OPT_NDBCLUSTER_DEFAULT 0
- #endif
- #include <nisam.h>
- #include <thr_alarm.h>
- #include <ft_global.h>
- #include <errmsg.h>
- #define mysqld_charset &my_charset_latin1
- #ifndef DBUG_OFF
- #define ONE_THREAD
- #endif
- #ifdef HAVE_purify
- #define IF_PURIFY(A,B) (A)
- #else
- #define IF_PURIFY(A,B) (B)
- #endif
- #ifndef INADDR_NONE
- #define INADDR_NONE -1 // Error value from inet_addr
- #endif
- /* stack traces are only supported on linux intel */
- #if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK)
- #define HAVE_STACK_TRACE_ON_SEGV
- #include "../pstack/pstack.h"
- char pstack_file_name[80];
- #endif /* __linux__ */
- /* We have HAVE_purify below as this speeds up the shutdown of MySQL */
- #if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
- #define HAVE_CLOSE_SERVER_SOCK 1
- #endif
- extern "C" { // Because of SCO 3.2V4.2
- #include <errno.h>
- #include <sys/stat.h>
- #ifndef __GNU_LIBRARY__
- #define __GNU_LIBRARY__ // Skip warnings in getopt.h
- #endif
- #include <my_getopt.h>
- #ifdef HAVE_SYSENT_H
- #include <sysent.h>
- #endif
- #ifdef HAVE_PWD_H
- #include <pwd.h> // For getpwent
- #endif
- #ifdef HAVE_GRP_H
- #include <grp.h>
- #endif
- #if defined(OS2)
- # include <sys/un.h>
- #elif !defined( __WIN__)
- # ifndef __NETWARE__
- #include <sys/resource.h>
- # endif /* __NETWARE__ */
- #ifdef HAVE_SYS_UN_H
- # include <sys/un.h>
- #endif
- #include <netdb.h>
- #ifdef HAVE_SELECT_H
- # include <select.h>
- #endif
- #ifdef HAVE_SYS_SELECT_H
- #include <sys/select.h>
- #endif
- #include <sys/utsname.h>
- #endif /* __WIN__ */
- #ifdef HAVE_LIBWRAP
- #include <tcpd.h>
- #include <syslog.h>
- #ifdef NEED_SYS_SYSLOG_H
- #include <sys/syslog.h>
- #endif /* NEED_SYS_SYSLOG_H */
- int allow_severity = LOG_INFO;
- int deny_severity = LOG_WARNING;
- #endif /* HAVE_LIBWRAP */
- #ifdef HAVE_SYS_MMAN_H
- #include <sys/mman.h>
- #endif
- #define zVOLSTATE_ACTIVE 6
- #define zVOLSTATE_DEACTIVE 2
- #define zVOLSTATE_MAINTENANCE 3
- #ifdef __NETWARE__
- #include <nks/netware.h>
- #include <nks/vm.h>
- #include <library.h>
- #include <monitor.h>
- #include <zOmni.h> //For NEB
- #include <neb.h> //For NEB
- #include <nebpub.h> //For NEB
- #include <zEvent.h> //For NSS event structures
- #include <zPublics.h>
- static void *neb_consumer_id= NULL; //For storing NEB consumer id
- static char datavolname[256]= {0};
- static VolumeID_t datavolid;
- static event_handle_t eh;
- static Report_t ref;
- static void *refneb= NULL;
- my_bool event_flag= FALSE;
- static int volumeid= -1;
- /* NEB event callback */
- unsigned long neb_event_callback(struct EventBlock *eblock);
- static void registerwithneb();
- static void getvolumename();
- static void getvolumeID(BYTE *volumeName);
- #endif /* __NETWARE__ */
-
- #ifdef _AIX41
- int initgroups(const char *,unsigned int);
- #endif
- #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
- #include <ieeefp.h>
- #ifdef HAVE_FP_EXCEPT // Fix type conflict
- typedef fp_except fp_except_t;
- #endif
- /* We can't handle floating point exceptions with threads, so disable
- this on freebsd
- */
- inline void reset_floating_point_exceptions()
- {
- /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
- #if defined(__i386__)
- fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
- FP_X_IMP));
- #else
- fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
- FP_X_IMP));
- #endif
- }
- #else
- #define reset_floating_point_exceptions()
- #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
- } /* cplusplus */
- #if defined(HAVE_LINUXTHREADS)
- #define THR_KILL_SIGNAL SIGINT
- #else
- #define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads
- #endif
- #define MYSQL_KILL_SIGNAL SIGTERM
- #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
- #include <sys/types.h>
- #else
- #include <my_pthread.h> // For thr_setconcurency()
- #endif
- #ifdef SOLARIS
- extern "C" int gethostname(char *name, int namelen);
- #endif
- /* Constants */
- const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
- const char *sql_mode_names[] =
- {
- "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
- "NO_DIR_IN_CREATE",
- "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
- "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
- "NO_AUTO_VALUE_ON_ZERO", NullS
- };
- TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
- sql_mode_names, NULL };
- const char *first_keyword= "first", *binary_keyword= "BINARY";
- const char *my_localhost= "localhost", *delayed_user= "DELAYED";
- #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
- #define GET_HA_ROWS GET_ULL
- #else
- #define GET_HA_ROWS GET_ULONG
- #endif
- bool opt_large_files= sizeof(my_off_t) > 4;
- /*
- Used with --help for detailed option
- */
- bool opt_help= 0;
- bool opt_verbose= 0;
- arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
- {{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
- {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
- {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
- {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row}};
- /* Global variables */
- bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
- bool opt_error_log= IF_WIN(1,0);
- bool opt_disable_networking=0, opt_skip_show_db=0;
- bool opt_character_set_client_handshake= 1;
- bool lower_case_table_names_used= 0;
- bool server_id_supplied = 0;
- bool opt_endinfo,using_udf_functions, locked_in_memory;
- bool opt_using_transactions, using_update_log;
- bool volatile abort_loop, select_thread_in_use, signal_thread_in_use;
- bool volatile ready_to_exit, shutdown_in_progress, grant_option;
- my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted
- my_bool opt_reckless_slave = 0;
- my_bool opt_enable_named_pipe= 0, opt_debugging= 0;
- my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
- my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
- my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
- my_bool opt_log_slave_updates= 0;
- my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam, opt_ndbcluster;
- #ifdef HAVE_NDBCLUSTER_DB
- const char *opt_ndbcluster_connectstring= 0;
- my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
- #endif
- my_bool opt_readonly, use_temp_pool, relay_log_purge;
- my_bool opt_sync_bdb_logs, opt_sync_frm, opt_allow_suspicious_udfs;
- my_bool opt_secure_auth= 0;
- my_bool opt_short_log_format= 0;
- my_bool opt_log_queries_not_using_indexes= 0;
- my_bool opt_log_slow_admin_statements= 0;
- my_bool lower_case_file_system= 0;
- my_bool opt_innodb_safe_binlog= 0;
- volatile bool mqh_used = 0;
- #ifdef HAVE_INITGROUPS
- static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
- #endif
- uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
- uint delay_key_write_options, protocol_version;
- uint lower_case_table_names;
- uint opt_crash_binlog_innodb;
- uint volatile thread_count, thread_running, kill_cached_threads, wake_thread;
- ulong back_log, connect_timeout, concurrency;
- ulong server_id, thd_startup_options;
- ulong table_cache_size, thread_stack, thread_stack_min, what_to_log;
- ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
- ulong open_files_limit, max_binlog_size, max_relay_log_size;
- ulong slave_net_timeout, slave_trans_retries;
- ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
- ulong query_cache_size=0;
- ulong com_stat[(uint) SQLCOM_END], com_other;
- ulong com_stmt_prepare, com_stmt_execute, com_stmt_send_long_data;
- ulong com_stmt_close, com_stmt_reset;
- ulong bytes_sent, bytes_received, net_big_packet_count;
- ulong refresh_version, flush_version; /* Increments on each reload */
- ulong query_id, long_query_count;
- ulong aborted_threads, killed_threads, aborted_connects;
- ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
- ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
- ulong delayed_insert_errors,flush_time, thread_created;
- ulong filesort_rows, filesort_range_count, filesort_scan_count;
- ulong filesort_merge_passes;
- ulong select_range_check_count, select_range_count, select_scan_count;
- ulong select_full_range_join_count,select_full_join_count;
- ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
- created_tmp_disk_tables=0;
- ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
- ulong max_connections,max_used_connections,
- max_connect_errors, max_user_connections = 0;
- ulong thread_id=1L,current_pid;
- ulong slow_launch_threads = 0, sync_binlog_period;
- ulong expire_logs_days = 0;
- ulong rpl_recovery_rank=0;
- ulong my_bind_addr; /* the address we bind to */
- volatile ulong cached_thread_count= 0;
- double log_10[32]; /* 10 potences */
- time_t start_time;
- char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
- char *default_tz_name;
- char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
- char* log_error_file_ptr= log_error_file;
- char mysql_real_data_home[FN_REFLEN],
- language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
- *mysqld_user,*mysqld_chroot, *opt_init_file,
- *opt_init_connect, *opt_init_slave,
- def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
- const key_map key_map_empty(0);
- key_map key_map_full(0); // Will be initialized later
- const char *opt_date_time_formats[3];
- char *language_ptr, *default_collation_name, *default_character_set_name;
- char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
- struct passwd *user_info;
- char server_version[SERVER_VERSION_LENGTH];
- char *mysqld_unix_port, *opt_mysql_tmpdir;
- char *my_bind_addr_str;
- const char **errmesg; /* Error messages */
- const char *myisam_recover_options_str="OFF";
- const char *myisam_stats_method_str="nulls_unequal";
- const char *sql_mode_str="OFF";
- /* name of reference on left espression in rewritten IN subquery */
- const char *in_left_expr_name= "<left expr>";
- /* name of additional condition */
- const char *in_additional_cond= "<IN COND>";
- /* classes for comparation parsing/processing */
- Eq_creator eq_creator;
- Ne_creator ne_creator;
- Gt_creator gt_creator;
- Lt_creator lt_creator;
- Ge_creator ge_creator;
- Le_creator le_creator;
- FILE *bootstrap_file;
- FILE *stderror_file=0;
- I_List<i_string_pair> replicate_rewrite_db;
- I_List<i_string> replicate_do_db, replicate_ignore_db;
- // allow the user to tell us which db to replicate and which to ignore
- I_List<i_string> binlog_do_db, binlog_ignore_db;
- I_List<THD> threads,thread_cache;
- I_List<NAMED_LIST> key_caches;
- struct system_variables global_system_variables;
- struct system_variables max_system_variables;
- MY_TMPDIR mysql_tmpdir_list;
- MY_BITMAP temp_pool;
- CHARSET_INFO *system_charset_info, *files_charset_info ;
- CHARSET_INFO *national_charset_info, *table_alias_charset;
- SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster,
- have_example_db, have_archive_db, have_csv_db;
- SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
- SHOW_COMP_OPTION have_geometry, have_rtree_keys;
- SHOW_COMP_OPTION have_crypt, have_compress;
- SHOW_COMP_OPTION have_blackhole_db;
- /* Thread specific variables */
- pthread_key(MEM_ROOT**,THR_MALLOC);
- pthread_key(THD*, THR_THD);
- pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
- LOCK_mapped_file, LOCK_status,
- LOCK_error_log, LOCK_uuid_generator,
- LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
- LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
- LOCK_global_system_variables,
- LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
- #ifdef HAVE_OPENSSL
- pthread_mutex_t LOCK_des_key_file;
- #endif
- rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
- pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
- COND_slave_start;
- pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
- pthread_t signal_thread;
- pthread_attr_t connection_attrib;
- /* replication parameters, if master_host is not NULL, we are a slave */
- uint master_port= MYSQL_PORT, master_connect_retry = 60;
- uint report_port= MYSQL_PORT;
- ulong master_retry_count=0;
- char *master_user, *master_password, *master_host, *master_info_file;
- char *relay_log_info_file, *report_user, *report_password, *report_host;
- char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
- my_bool master_ssl;
- char *master_ssl_key, *master_ssl_cert;
- char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher;
- /* Static variables */
- static bool kill_in_progress, segfaulted;
- static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log;
- static int cleanup_done;
- static ulong opt_specialflag, opt_myisam_block_size;
- static char *opt_logname, *opt_update_logname, *opt_binlog_index_name;
- static char *opt_slow_logname;
- static char *mysql_home_ptr, *pidfile_name_ptr;
- static char **defaults_argv;
- static char *opt_bin_logname;
- static my_socket unix_sock,ip_sock;
- static pthread_t select_thread;
- struct rand_struct sql_rand; // used by sql_class.cc:THD::THD()
- /* OS specific variables */
- #ifdef __WIN__
- #undef getpid
- #include <process.h>
- static pthread_cond_t COND_handler_count;
- static uint handler_count;
- static bool start_mode=0, use_opt_args;
- static int opt_argc;
- static char **opt_argv;
- #if !defined(EMBEDDED_LIBRARY)
- static HANDLE hEventShutdown;
- static char shutdown_event_name[40];
- #include "nt_servc.h"
- static NTService Service; // Service object for WinNT
- #endif /* EMBEDDED_LIBRARY */
- #endif /* __WIN__ */
- #ifdef __NT__
- static char pipe_name[512];
- static SECURITY_ATTRIBUTES saPipeSecurity;
- static SECURITY_DESCRIPTOR sdPipeDescriptor;
- static HANDLE hPipe = INVALID_HANDLE_VALUE;
- #endif
- #ifdef OS2
- pthread_cond_t eventShutdown;
- #endif
- #ifndef EMBEDDED_LIBRARY
- bool mysqld_embedded=0;
- #else
- bool mysqld_embedded=1;
- #endif
- #ifndef DBUG_OFF
- static const char* default_dbug_option;
- #endif
- #ifdef HAVE_LIBWRAP
- char *libwrapName= NULL;
- #endif
- #ifdef HAVE_QUERY_CACHE
- ulong query_cache_limit= 0;
- ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
- Query_cache query_cache;
- #endif
- #ifdef HAVE_SMEM
- char *shared_memory_base_name= default_shared_memory_base_name;
- bool opt_enable_shared_memory;
- HANDLE smem_event_connect_request= 0;
- #endif
- #include "sslopt-vars.h"
- #ifdef HAVE_OPENSSL
- #include <openssl/crypto.h>
- typedef struct CRYPTO_dynlock_value
- {
- rw_lock_t lock;
- } openssl_lock_t;
- char *des_key_file;
- struct st_VioSSLAcceptorFd *ssl_acceptor_fd;
- static openssl_lock_t *openssl_stdlocks;
- static openssl_lock_t *openssl_dynlock_create(const char *, int);
- static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
- static void openssl_lock_function(int, int, const char *, int);
- static void openssl_lock(int, openssl_lock_t *, const char *, int);
- static unsigned long openssl_id_function();
- #endif /* HAVE_OPENSSL */
- /* Function declarations */
- static void start_signal_handler(void);
- extern "C" pthread_handler_decl(signal_hand, arg);
- static void mysql_init_variables(void);
- static void get_options(int argc,char **argv);
- static void set_server_version(void);
- static int init_thread_environment();
- static char *get_relative_path(const char *path);
- static void fix_paths(void);
- extern "C" pthread_handler_decl(handle_connections_sockets,arg);
- extern "C" pthread_handler_decl(kill_server_thread,arg);
- static int bootstrap(FILE *file);
- static void close_server_sock();
- static bool read_init_file(char *file_name);
- #ifdef __NT__
- extern "C" pthread_handler_decl(handle_connections_namedpipes,arg);
- #endif
- #ifdef HAVE_SMEM
- static pthread_handler_decl(handle_connections_shared_memory,arg);
- #endif
- extern "C" pthread_handler_decl(handle_slave,arg);
- static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
- static void clean_up(bool print_message);
- static void clean_up_mutexes(void);
- static void wait_for_signal_thread_to_end(void);
- static int test_if_case_insensitive(const char *dir_name);
- static void create_pid_file();
- #ifndef EMBEDDED_LIBRARY
- /****************************************************************************
- ** Code to end mysqld
- ****************************************************************************/
- static void close_connections(void)
- {
- #ifdef EXTRA_DEBUG
- int count=0;
- #endif
- DBUG_ENTER("close_connections");
- /* Clear thread cache */
- kill_cached_threads++;
- flush_thread_cache();
- /* kill flush thread */
- (void) pthread_mutex_lock(&LOCK_manager);
- if (manager_thread_in_use)
- {
- DBUG_PRINT("quit",("killing manager thread: %lx",manager_thread));
- (void) pthread_cond_signal(&COND_manager);
- }
- (void) pthread_mutex_unlock(&LOCK_manager);
- /* kill connection thread */
- #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
- DBUG_PRINT("quit",("waiting for select thread: %lx",select_thread));
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (select_thread_in_use)
- {
- struct timespec abstime;
- int error;
- LINT_INIT(error);
- DBUG_PRINT("info",("Waiting for select thread"));
- #ifndef DONT_USE_THR_ALARM
- if (pthread_kill(select_thread,THR_CLIENT_ALARM))
- break; // allready dead
- #endif
- set_timespec(abstime, 2);
- for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
- {
- error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
- &abstime);
- if (error != EINTR)
- break;
- }
- #ifdef EXTRA_DEBUG
- if (error != 0 && !count++)
- sql_print_error("Got error %d from pthread_cond_timedwait",error);
- #endif
- close_server_sock();
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- #endif /* __WIN__ */
- /* Abort listening to new connections */
- DBUG_PRINT("quit",("Closing sockets"));
- if ( !opt_disable_networking )
- {
- if (ip_sock != INVALID_SOCKET)
- {
- (void) shutdown(ip_sock,2);
- (void) closesocket(ip_sock);
- ip_sock= INVALID_SOCKET;
- }
- }
- #ifdef __NT__
- if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
- {
- HANDLE temp;
- DBUG_PRINT( "quit", ("Closing named pipes") );
- /* Create connection to the handle named pipe handler to break the loop */
- if ((temp = CreateFile(pipe_name,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL )) != INVALID_HANDLE_VALUE)
- {
- WaitNamedPipe(pipe_name, 1000);
- DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
- SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
- CancelIo(temp);
- DisconnectNamedPipe(temp);
- CloseHandle(temp);
- }
- }
- #endif
- #ifdef HAVE_SYS_UN_H
- if (unix_sock != INVALID_SOCKET)
- {
- (void) shutdown(unix_sock,2);
- (void) closesocket(unix_sock);
- (void) unlink(mysqld_unix_port);
- unix_sock= INVALID_SOCKET;
- }
- #endif
- end_thr_alarm(0); // Abort old alarms.
- /*
- First signal all threads that it's time to die
- This will give the threads some time to gracefully abort their
- statements and inform their clients that the server is about to die.
- */
- THD *tmp;
- (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
- I_List_iterator<THD> it(threads);
- while ((tmp=it++))
- {
- DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
- tmp->thread_id));
- /* We skip slave threads on this first loop through. */
- if (tmp->slave_thread) continue;
- tmp->killed= 1;
- if (tmp->mysys_var)
- {
- tmp->mysys_var->abort=1;
- pthread_mutex_lock(&tmp->mysys_var->mutex);
- if (tmp->mysys_var->current_cond)
- {
- pthread_mutex_lock(tmp->mysys_var->current_mutex);
- pthread_cond_broadcast(tmp->mysys_var->current_cond);
- pthread_mutex_unlock(tmp->mysys_var->current_mutex);
- }
- pthread_mutex_unlock(&tmp->mysys_var->mutex);
- }
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
- end_slave();
- if (thread_count)
- sleep(2); // Give threads time to die
- /*
- Force remaining threads to die by closing the connection to the client
- This will ensure that threads that are waiting for a command from the
- client on a blocking read call are aborted.
- */
- for (;;)
- {
- DBUG_PRINT("quit",("Locking LOCK_thread_count"));
- (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
- if (!(tmp=threads.get()))
- {
- DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- break;
- }
- #ifndef __bsdi__ // Bug in BSDI kernel
- if (tmp->vio_ok())
- {
- if (global_system_variables.log_warnings)
- sql_print_warning(ER(ER_FORCING_CLOSE),my_progname,
- tmp->thread_id,tmp->user ? tmp->user : "");
- close_connection(tmp,0,0);
- }
- #endif
- DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- }
- /* All threads has now been aborted */
- DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (thread_count)
- {
- (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_PRINT("quit",("close_connections thread"));
- DBUG_VOID_RETURN;
- }
- #endif /*EMBEDDED_LIBRARY*/
- static void close_server_sock()
- {
- #ifdef HAVE_CLOSE_SERVER_SOCK
- DBUG_ENTER("close_server_sock");
- my_socket tmp_sock;
- tmp_sock=ip_sock;
- if (tmp_sock != INVALID_SOCKET)
- {
- ip_sock=INVALID_SOCKET;
- DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
- VOID(shutdown(tmp_sock,2));
- #if defined(__NETWARE__)
- /*
- The following code is disabled for normal systems as it causes MySQL
- to hang on AIX 4.3 during shutdown
- */
- DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
- VOID(closesocket(tmp_sock));
- #endif
- }
- tmp_sock=unix_sock;
- if (tmp_sock != INVALID_SOCKET)
- {
- unix_sock=INVALID_SOCKET;
- DBUG_PRINT("info",("calling shutdown on unix socket"));
- VOID(shutdown(tmp_sock,2));
- #if defined(__NETWARE__)
- /*
- The following code is disabled for normal systems as it may cause MySQL
- to hang on AIX 4.3 during shutdown
- */
- DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
- VOID(closesocket(tmp_sock));
- #endif
- VOID(unlink(mysqld_unix_port));
- }
- DBUG_VOID_RETURN;
- #endif
- }
- void kill_mysql(void)
- {
- DBUG_ENTER("kill_mysql");
- #ifdef SIGNALS_DONT_BREAK_READ
- abort_loop=1; // Break connection loops
- close_server_sock(); // Force accept to wake up
- #endif
- #if defined(__WIN__)
- #if !defined(EMBEDDED_LIBRARY)
- {
- if (!SetEvent(hEventShutdown))
- {
- DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
- }
- /*
- or:
- HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
- SetEvent(hEventShutdown);
- CloseHandle(hEvent);
- */
- }
- #endif
- #elif defined(OS2)
- pthread_cond_signal( &eventShutdown); // post semaphore
- #elif defined(HAVE_PTHREAD_KILL)
- if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
- {
- DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
- }
- #elif !defined(SIGNALS_DONT_BREAK_READ)
- kill(current_pid, MYSQL_KILL_SIGNAL);
- #endif
- DBUG_PRINT("quit",("After pthread_kill"));
- shutdown_in_progress=1; // Safety if kill didn't work
- #ifdef SIGNALS_DONT_BREAK_READ
- if (!kill_in_progress)
- {
- pthread_t tmp;
- abort_loop=1;
- if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
- (void*) 0))
- sql_print_error("Can't create thread to kill server");
- }
- #endif
- DBUG_VOID_RETURN;
- }
- /* Force server down. kill all connections and threads and exit */
- #if defined(OS2) || defined(__NETWARE__)
- extern "C" void kill_server(int sig_ptr)
- #define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
- #elif !defined(__WIN__)
- static void *kill_server(void *sig_ptr)
- #define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
- #else
- static void __cdecl kill_server(int sig_ptr)
- #define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
- #endif
- {
- int sig=(int) (long) sig_ptr; // This is passed a int
- DBUG_ENTER("kill_server");
- #ifndef EMBEDDED_LIBRARY
- // if there is a signal during the kill in progress, ignore the other
- if (kill_in_progress) // Safety
- RETURN_FROM_KILL_SERVER;
- kill_in_progress=TRUE;
- abort_loop=1; // This should be set
- my_sigset(sig,SIG_IGN);
- if (sig == MYSQL_KILL_SIGNAL || sig == 0)
- sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname);
- else
- sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
- #if defined(HAVE_SMEM) && defined(__WIN__)
- /*
- Send event to smem_event_connect_request for aborting
- */
- if (!SetEvent(smem_event_connect_request))
- {
- DBUG_PRINT("error",
- ("Got error: %ld from SetEvent of smem_event_connect_request",
- GetLastError()));
- }
- #endif
-
- #if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
- my_thread_init(); // If this is a new thread
- #endif
- close_connections();
- if (sig != MYSQL_KILL_SIGNAL && sig != 0)
- unireg_abort(1); /* purecov: inspected */
- else
- unireg_end();
- #ifdef __NETWARE__
- if (!event_flag)
- pthread_join(select_thread, NULL); // wait for main thread
- #endif /* __NETWARE__ */
- pthread_exit(0); /* purecov: deadcode */
- #endif /* EMBEDDED_LIBRARY */
- RETURN_FROM_KILL_SERVER;
- }
- #if defined(USE_ONE_SIGNAL_HAND) || (defined(__NETWARE__) && defined(SIGNALS_DONT_BREAK_READ))
- extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
- {
- my_thread_init(); // Initialize new thread
- kill_server(0);
- my_thread_end(); // Normally never reached
- return 0;
- }
- #endif
- extern "C" sig_handler print_signal_warning(int sig)
- {
- if (!DBUG_IN_USE)
- {
- if (global_system_variables.log_warnings)
- sql_print_warning("Got signal %d from thread %d",
- sig,my_thread_id());
- }
- #ifdef DONT_REMEMBER_SIGNAL
- my_sigset(sig,print_signal_warning); /* int. thread system calls */
- #endif
- #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- if (sig == SIGALRM)
- alarm(2); /* reschedule alarm */
- #endif
- }
- /*
- cleanup all memory and end program nicely
- SYNOPSIS
- unireg_end()
- NOTES
- This function never returns.
- If SIGNALS_DONT_BREAK_READ is defined, this function is called
- by the main thread. To get MySQL to shut down nicely in this case
- (Mac OS X) we have to call exit() instead if pthread_exit().
- */
- #ifndef EMBEDDED_LIBRARY
- void unireg_end(void)
- {
- clean_up(1);
- my_thread_end();
- #if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
- exit(0);
- #else
- pthread_exit(0); // Exit is in main thread
- #endif
- }
- extern "C" void unireg_abort(int exit_code)
- {
- DBUG_ENTER("unireg_abort");
- if (exit_code)
- sql_print_error("Abortingn");
- clean_up(exit_code || !opt_bootstrap); /* purecov: inspected */
- DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
- wait_for_signal_thread_to_end();
- clean_up_mutexes();
- my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
- exit(exit_code); /* purecov: inspected */
- }
- #endif
- void clean_up(bool print_message)
- {
- DBUG_PRINT("exit",("clean_up"));
- if (cleanup_done++)
- return; /* purecov: inspected */
- mysql_log.cleanup();
- mysql_slow_log.cleanup();
- mysql_update_log.cleanup();
- mysql_bin_log.cleanup();
- #ifdef HAVE_REPLICATION
- if (use_slave_mask)
- bitmap_free(&slave_error_mask);
- #endif
- my_tz_free();
- my_dbopt_free();
- #ifndef NO_EMBEDDED_ACCESS_CHECKS
- acl_free(1);
- grant_free();
- #endif
- query_cache_destroy();
- table_cache_free();
- hostname_cache_free();
- item_user_lock_free();
- lex_free(); /* Free some memory */
- set_var_free();
- free_charsets();
- #ifdef HAVE_DLOPEN
- if (!opt_noacl)
- udf_free();
- #endif
- (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
- delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
- multi_keycache_free();
- end_thr_alarm(1); /* Free allocated memory */
- #ifdef USE_RAID
- end_raid();
- #endif
- my_free_open_file_info();
- my_free((char*) global_system_variables.date_format,
- MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) global_system_variables.time_format,
- MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) global_system_variables.datetime_format,
- MYF(MY_ALLOW_ZERO_PTR));
- if (defaults_argv)
- free_defaults(defaults_argv);
- my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
- my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
- free_tmpdir(&mysql_tmpdir_list);
- #ifdef HAVE_REPLICATION
- my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
- #endif
- x_free(opt_bin_logname);
- x_free(opt_relay_logname);
- bitmap_free(&temp_pool);
- free_max_user_conn();
- #ifdef HAVE_REPLICATION
- end_slave_list();
- free_list(&replicate_do_db);
- free_list(&replicate_ignore_db);
- free_list(&binlog_do_db);
- free_list(&binlog_ignore_db);
- free_list(&replicate_rewrite_db);
- #endif
- #ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
- #endif /* HAVE_OPENSSL */
- #ifdef USE_REGEX
- my_regex_end();
- #endif
- if (print_message && errmesg)
- sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
- #if !defined(EMBEDDED_LIBRARY)
- if (!opt_bootstrap)
- (void) my_delete(pidfile_name,MYF(0)); // This may not always exist
- #endif
- x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
- DBUG_PRINT("quit", ("Error messages freed"));
- /* Tell main we are ready */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- DBUG_PRINT("quit", ("got thread count lock"));
- ready_to_exit=1;
- /* do the broadcast inside the lock to ensure that my_end() is not called */
- (void) pthread_cond_broadcast(&COND_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- /*
- The following lines may never be executed as the main thread may have
- killed us
- */
- DBUG_PRINT("quit", ("done with cleanup"));
- } /* clean_up */
- /*
- This is mainly needed when running with purify, but it's still nice to
- know that all child threads have died when mysqld exits
- */
- static void wait_for_signal_thread_to_end()
- {
- #ifndef __NETWARE__
- uint i;
- /*
- Wait up to 10 seconds for signal thread to die. We use this mainly to
- avoid getting warnings that my_thread_end has not been called
- */
- for (i= 0 ; i < 100 && signal_thread_in_use; i++)
- {
- if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
- break;
- my_sleep(100); // Give it time to die
- }
- #endif
- }
- static void clean_up_mutexes()
- {
- (void) pthread_mutex_destroy(&LOCK_mysql_create_db);
- (void) pthread_mutex_destroy(&LOCK_Acl);
- (void) rwlock_destroy(&LOCK_grant);
- (void) pthread_mutex_destroy(&LOCK_open);
- (void) pthread_mutex_destroy(&LOCK_thread_count);
- (void) pthread_mutex_destroy(&LOCK_mapped_file);
- (void) pthread_mutex_destroy(&LOCK_status);
- (void) pthread_mutex_destroy(&LOCK_error_log);
- (void) pthread_mutex_destroy(&LOCK_delayed_insert);
- (void) pthread_mutex_destroy(&LOCK_delayed_status);
- (void) pthread_mutex_destroy(&LOCK_delayed_create);
- (void) pthread_mutex_destroy(&LOCK_manager);
- (void) pthread_mutex_destroy(&LOCK_crypt);
- (void) pthread_mutex_destroy(&LOCK_bytes_sent);
- (void) pthread_mutex_destroy(&LOCK_bytes_received);
- (void) pthread_mutex_destroy(&LOCK_user_conn);
- #ifdef HAVE_OPENSSL
- (void) pthread_mutex_destroy(&LOCK_des_key_file);
- for (int i= 0; i < CRYPTO_num_locks(); ++i)
- (void) rwlock_destroy(&openssl_stdlocks[i].lock);
- OPENSSL_free(openssl_stdlocks);
- #endif
- #ifdef HAVE_REPLICATION
- (void) pthread_mutex_destroy(&LOCK_rpl_status);
- (void) pthread_cond_destroy(&COND_rpl_status);
- #endif
- (void) pthread_mutex_destroy(&LOCK_active_mi);
- (void) rwlock_destroy(&LOCK_sys_init_connect);
- (void) rwlock_destroy(&LOCK_sys_init_slave);
- (void) pthread_mutex_destroy(&LOCK_global_system_variables);
- (void) pthread_cond_destroy(&COND_thread_count);
- (void) pthread_cond_destroy(&COND_refresh);
- (void) pthread_cond_destroy(&COND_thread_cache);
- (void) pthread_cond_destroy(&COND_flush_thread_cache);
- (void) pthread_cond_destroy(&COND_manager);
- }
- /****************************************************************************
- ** Init IP and UNIX socket
- ****************************************************************************/
- static void set_ports()
- {
- char *env;
- if (!mysqld_port && !opt_disable_networking)
- { // Get port if not from commandline
- struct servent *serv_ptr;
- mysqld_port= MYSQL_PORT;
- if ((serv_ptr= getservbyname("mysql", "tcp")))
- mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
- if ((env = getenv("MYSQL_TCP_PORT")))
- mysqld_port= (uint) atoi(env); /* purecov: inspected */
- }
- if (!mysqld_unix_port)
- {
- #ifdef __WIN__
- mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
- #else
- mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
- #endif
- if ((env = getenv("MYSQL_UNIX_PORT")))
- mysqld_unix_port= env; /* purecov: inspected */
- }
- }
- #ifndef EMBEDDED_LIBRARY
- /* Change to run as another user if started with --user */
- static struct passwd *check_user(const char *user)
- {
- #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- struct passwd *user_info;
- uid_t user_id= geteuid();
- // Don't bother if we aren't superuser
- if (user_id)
- {
- if (user)
- {
- // Don't give a warning, if real user is same as given with --user
- user_info= getpwnam(user);
- if ((!user_info || user_id != user_info->pw_uid) &&
- global_system_variables.log_warnings)
- sql_print_warning(
- "One can only use the --user switch if running as rootn");
- }
- return NULL;
- }
- if (!user)
- {
- if (!opt_bootstrap)
- {
- sql_print_error("Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root!n");
- unireg_abort(1);
- }
- return NULL;
- }
- if (!strcmp(user,"root"))
- return NULL; // Avoid problem with dynamic libraries
- if (!(user_info= getpwnam(user)))
- {
- // Allow a numeric uid to be used
- const char *pos;
- for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
- if (*pos) // Not numeric id
- goto err;
- if (!(user_info= getpwuid(atoi(user))))
- goto err;
- else
- return user_info;
- }
- else
- return user_info;
- err:
- sql_print_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!n",user);
- unireg_abort(1);
- #endif
- return NULL;
- }
- static void set_user(const char *user, struct passwd *user_info)
- {
- #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- DBUG_ASSERT(user_info);
- #ifdef HAVE_INITGROUPS
- /*
- We can get a SIGSEGV when calling initgroups() on some systems when NSS
- is configured to use LDAP and the server is statically linked. We set
- calling_initgroups as a flag to the SIGSEGV handler that is then used to
- output a specific message to help the user resolve this problem.
- */
- calling_initgroups= TRUE;
- initgroups((char*) user, user_info->pw_gid);
- calling_initgroups= FALSE;
- #endif
- if (setgid(user_info->pw_gid) == -1)
- {
- sql_perror("setgid");
- unireg_abort(1);
- }
- if (setuid(user_info->pw_uid) == -1)
- {
- sql_perror("setuid");
- unireg_abort(1);
- }
- #endif
- }
- static void set_effective_user(struct passwd *user_info)
- {
- #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- DBUG_ASSERT(user_info);
- if (setregid((gid_t)-1, user_info->pw_gid) == -1)
- {
- sql_perror("setregid");
- unireg_abort(1);
- }
- if (setreuid((uid_t)-1, user_info->pw_uid) == -1)
- {
- sql_perror("setreuid");
- unireg_abort(1);
- }
- #endif
- }
- /* Change root user if started with --chroot */
- static void set_root(const char *path)
- {
- #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
- if (chroot(path) == -1)
- {
- sql_perror("chroot");
- unireg_abort(1);
- }
- my_setwd("/", MYF(0));
- #endif
- }
- static void server_init(void)
- {
- struct sockaddr_in IPaddr;
- #ifdef HAVE_SYS_UN_H
- struct sockaddr_un UNIXaddr;
- #endif
- int arg=1;
- DBUG_ENTER("server_init");
- #ifdef __WIN__
- if ( !opt_disable_networking )
- {
- WSADATA WsaData;
- if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
- {
- my_message(0,"WSAStartup Failedn",MYF(0));
- unireg_abort(1);
- }
- }
- #endif /* __WIN__ */
- set_ports();
- if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
- {
- DBUG_PRINT("general",("IP Socket is %d",mysqld_port));
- ip_sock = socket(AF_INET, SOCK_STREAM, 0);
- if (ip_sock == INVALID_SOCKET)
- {
- DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
- sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */
- unireg_abort(1); /* purecov: tested */
- }
- bzero((char*) &IPaddr, sizeof(IPaddr));
- IPaddr.sin_family = AF_INET;
- IPaddr.sin_addr.s_addr = my_bind_addr;
- IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port);
- #ifndef __WIN__
- /*
- We should not use SO_REUSEADDR on windows as this would enable a
- user to open two mysqld servers with the same TCP/IP port.
- */
- (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
- #endif /* __WIN__ */
- if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr),
- sizeof(IPaddr)) < 0)
- {
- DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
- sql_perror("Can't start server: Bind on TCP/IP port");
- sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
- unireg_abort(1);
- }
- if (listen(ip_sock,(int) back_log) < 0)
- {
- sql_perror("Can't start server: listen() on TCP/IP port");
- sql_print_error("listen() on TCP/IP failed with error %d",
- socket_errno);
- unireg_abort(1);
- }
- }
- if ((user_info= check_user(mysqld_user)))
- {
- #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
- if (locked_in_memory) // getuid() == 0 here
- set_effective_user(user_info);
- else
- #endif
- set_user(mysqld_user, user_info);
- }
- #ifdef __NT__
- /* create named pipe */
- if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
- opt_enable_named_pipe)
- {
-
- pipe_name[sizeof(pipe_name)-1]= 0; /* Safety if too long string */
- strxnmov(pipe_name, sizeof(pipe_name)-1, "\\.\pipe\",
- mysqld_unix_port, NullS);
- bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
- bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
- if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
- SECURITY_DESCRIPTOR_REVISION))
- {
- sql_perror("Can't start server : Initialize security descriptor");
- unireg_abort(1);
- }
- if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
- {
- sql_perror("Can't start server : Set security descriptor");
- unireg_abort(1);
- }
- saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES );
- saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
- saPipeSecurity.bInheritHandle = FALSE;
- if ((hPipe= CreateNamedPipe(pipe_name,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_BYTE |
- PIPE_READMODE_BYTE |
- PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES,
- (int) global_system_variables.net_buffer_length,
- (int) global_system_variables.net_buffer_length,
- NMPWAIT_USE_DEFAULT_WAIT,
- &saPipeSecurity)) == INVALID_HANDLE_VALUE)
- {
- LPVOID lpMsgBuf;
- int error=GetLastError();
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL );
- MessageBox( NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
- MB_OK|MB_ICONINFORMATION );
- LocalFree( lpMsgBuf );
- unireg_abort(1);
- }
- }
- #endif
- #if defined(HAVE_SYS_UN_H)
- /*
- ** Create the UNIX socket
- */
- if (mysqld_unix_port[0] && !opt_bootstrap)
- {
- DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
- if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
- {
- sql_print_error("The socket file path is too long (> %d): %s",
- sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
- unireg_abort(1);
- }
- if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
- {
- sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
- unireg_abort(1); /* purecov: inspected */
- }
- bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
- UNIXaddr.sun_family = AF_UNIX;
- strmov(UNIXaddr.sun_path, mysqld_unix_port);
- (void) unlink(mysqld_unix_port);
- (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
- sizeof(arg));
- umask(0);
- if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
- sizeof(UNIXaddr)) < 0)
- {
- sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
- sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
- unireg_abort(1); /* purecov: tested */
- }
- umask(((~my_umask) & 0666));
- #if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
- (void) chmod(mysqld_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */
- #endif
- if (listen(unix_sock,(int) back_log) < 0)
- sql_print_warning("listen() on Unix socket failed with error %d",
- socket_errno);
- }
- #endif
- DBUG_PRINT("info",("server started"));
- DBUG_VOID_RETURN;
- }
- #endif /*!EMBEDDED_LIBRARY*/
- void yyerror(const char *s)
- {
- THD *thd=current_thd;
- char *yytext= (char*) thd->lex->tok_start;
- /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
- if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
- s=ER(ER_SYNTAX_ERROR);
- net_printf(thd,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
- thd->lex->yylineno);
- }
- #ifndef EMBEDDED_LIBRARY
- /*
- Close a connection
- SYNOPSIS
- close_connection()
- thd Thread handle
- errcode Error code to print to console
- lock 1 if we have have to lock LOCK_thread_count
- NOTES
- For the connection that is doing shutdown, this is called twice
- */
- void close_connection(THD *thd, uint errcode, bool lock)
- {
- st_vio *vio;
- DBUG_ENTER("close_connection");
- DBUG_PRINT("enter",("fd: %s error: '%s'",
- thd->net.vio ? vio_description(thd->net.vio) :
- "(not connected)",
- errcode ? ER(errcode) : ""));
- if (lock)
- (void) pthread_mutex_lock(&LOCK_thread_count);
- thd->killed=1;
- if ((vio=thd->net.vio) != 0)
- {
- if (errcode)
- send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
- vio_close(vio); /* vio is freed in delete thd */
- }
- if (lock)
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_VOID_RETURN;
- }
- #endif /* EMBEDDED_LIBRARY */
- /* Called when a thread is aborted */
- /* ARGSUSED */
- extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
- {
- THD *thd=current_thd;
- DBUG_ENTER("end_thread_signal");
- if (thd && ! thd->bootstrap)
- {
- statistic_increment(killed_threads, &LOCK_status);
- end_thread(thd,0);
- }
- DBUG_VOID_RETURN; /* purecov: deadcode */
- }
- void end_thread(THD *thd, bool put_in_cache)
- {
- DBUG_ENTER("end_thread");
- thd->cleanup();
- (void) pthread_mutex_lock(&LOCK_thread_count);
- thread_count--;
- delete thd;
- if (put_in_cache && cached_thread_count < thread_cache_size &&
- ! abort_loop && !kill_cached_threads)
- {
- /* Don't kill the thread, just put it in cache for reuse */
- DBUG_PRINT("info", ("Adding thread to cache"))
- cached_thread_count++;
- while (!abort_loop && ! wake_thread && ! kill_cached_threads)
- (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
- cached_thread_count--;
- if (kill_cached_threads)
- pthread_cond_signal(&COND_flush_thread_cache);
- if (wake_thread)
- {
- wake_thread--;
- thd=thread_cache.get();
- thd->real_id=pthread_self();
- (void) thd->store_globals();
- thd->thr_create_time= time(NULL);
- threads.append(thd);
- pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_VOID_RETURN;
- }
- }
- DBUG_PRINT("info", ("sending a broadcast"))
- /* Tell main we are ready */
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- /* It's safe to broadcast outside a lock (COND... is not deleted here) */
- (void) pthread_cond_broadcast(&COND_thread_count);
- DBUG_PRINT("info", ("unlocked thread_count mutex"))
- #ifdef ONE_THREAD
- if (!(test_flags & TEST_NO_THREADS)) // For debugging under Linux
- #endif
- {
- my_thread_end();
- pthread_exit(0);
- }
- DBUG_VOID_RETURN;
- }
- /* Start a cached thread. LOCK_thread_count is locked on entry */
- static void start_cached_thread(THD *thd)
- {
- thread_cache.append(thd);
- wake_thread++;
- thread_count++;
- pthread_cond_signal(&COND_thread_cache);
- }
- void flush_thread_cache()
- {
- (void) pthread_mutex_lock(&LOCK_thread_count);
- kill_cached_threads++;
- while (cached_thread_count)
- {
- pthread_cond_broadcast(&COND_thread_cache);
- pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count);
- }
- kill_cached_threads--;
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- }
- /******************************************************************************
- Setup a signal thread with handles all signals.
- Because Linux doesn't support schemas use a mutex to check that
- the signal thread is ready before continuing
- ******************************************************************************/
- #if defined(__WIN__) || defined(OS2)
- static void init_signals(void)
- {
- int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
- for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
- signal( signals[i], kill_server) ;
- #if defined(__WIN__)
- signal(SIGBREAK,SIG_IGN); //ignore SIGBREAK for NT
- #else
- signal(SIGBREAK, kill_server);
- #endif
- }
- static void start_signal_handler(void)
- {
- // Save vm id of this process
- if (!opt_bootstrap)
- create_pid_file();
- }
- static void check_data_home(const char *path)
- {}
- #elif defined(__NETWARE__)
- // down server event callback
- void mysql_down_server_cb(void *, void *)
- {
- event_flag = TRUE;
- kill_server(0);
- }
- // destroy callback resources
- void mysql_cb_destroy(void *)
- {
- UnRegisterEventNotification(eh); // cleanup down event notification
- NX_UNWRAP_INTERFACE(ref);
- /* Deregister NSS volume deactivation event */
- NX_UNWRAP_INTERFACE(refneb);
- if (neb_consumer_id)
- UnRegisterConsumer(neb_consumer_id, NULL);
- }
- // initialize callbacks
- void mysql_cb_init()
- {
- // register for down server event
- void *handle = getnlmhandle();
- rtag_t rt= AllocateResourceTag(handle, "MySQL Down Server Callback",
- EventSignature);
- NX_WRAP_INTERFACE((void *)mysql_down_server_cb, 2, (void **)&ref);
- eh= RegisterForEventNotification(rt, EVENT_PRE_DOWN_SERVER,
- EVENT_PRIORITY_APPLICATION,
- NULL, ref, NULL);
- /*
- Register for volume deactivation event
- Wrap the callback function, as it is called by non-LibC thread
- */
- (void *) NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
- registerwithneb();
- NXVmRegisterExitHandler(mysql_cb_destroy, NULL); // clean-up
- }
- /* To get the name of the NetWare volume having MySQL data folder */
- static void getvolumename()
- {
- char *p;
- /*
- We assume that data path is already set.
- If not it won't come here. Terminate after volume name
- */
- if ((p= strchr(mysql_real_data_home, ':')))
- strmake(datavolname, mysql_real_data_home,
- (uint) (p - mysql_real_data_home));
- }
- /*
- Registering with NEB for NSS Volume Deactivation event
- */
- static void registerwithneb()
- {
- ConsumerRegistrationInfo reg_info;
-
- /* Clear NEB registration structure */
- bzero((char*) ®_info, sizeof(struct ConsumerRegistrationInfo));
- /* Fill the NEB consumer information structure */
- reg_info.CRIVersion= 1; // NEB version
- /* NEB Consumer name */
- reg_info.CRIConsumerName= (BYTE *) "MySQL Database Server";
- /* Event of interest */
- reg_info.CRIEventName= (BYTE *) "NSS.ChangeVolState.Enter";
- reg_info.CRIUserParameter= NULL; // Consumer Info
- reg_info.CRIEventFlags= 0; // Event flags
- /* Consumer NLM handle */
- reg_info.CRIOwnerID= (LoadDefinitionStructure *)getnlmhandle();
- reg_info.CRIConsumerESR= NULL; // No consumer ESR required
- reg_info.CRISecurityToken= 0; // No security token for the event
- reg_info.CRIConsumerFlags= 0; // SMP_ENABLED_BIT;
- reg_info.CRIFilterName= 0; // No event filtering
- reg_info.CRIFilterDataLength= 0; // No filtering data
- reg_info.CRIFilterData= 0; // No filtering data
- /* Callback function for the event */
- (void *)reg_info.CRIConsumerCallback= (void *) refneb;
- reg_info.CRIOrder= 0; // Event callback order
- reg_info.CRIConsumerType= CHECK_CONSUMER; // Consumer type
- /* Register for the event with NEB */
- if (RegisterConsumer(®_info))
- {
- consoleprintf("Failed to register for NSS Volume Deactivation event n");
- return;
- }
- /* This ID is required for deregistration */
- neb_consumer_id= reg_info.CRIConsumerID;
- /* Get MySQL data volume name, stored in global variable datavolname */
- getvolumename();
- /*
- Get the NSS volume ID of the MySQL Data volume.
- Volume ID is stored in a global variable
- */
- getvolumeID((BYTE*) datavolname);
- }
- /*
- Callback for NSS Volume Deactivation event
- */
- ulong neb_event_callback(struct EventBlock *eblock)
- {
- EventChangeVolStateEnter_s *voldata;
- extern bool nw_panic;
- voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData;
- /* Deactivation of a volume */
- if ((voldata->oldState == zVOLSTATE_ACTIVE &&
- voldata->newState == zVOLSTATE_DEACTIVE ||
- voldata->newState == zVOLSTATE_MAINTENANCE))
- {
- /*
- Ensure that we bring down MySQL server only for MySQL data
- volume deactivation
- */
- if (!memcmp(&voldata->volID, &datavolid, sizeof(VolumeID_t)))
- {
- consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server n");
- event_flag= TRUE;
- nw_panic = TRUE;
- event_flag= TRUE;
- kill_server(0);
-
- }
- }
- return 0;
- }
- /*
- Function to get NSS volume ID of the MySQL data
- */
- #define ADMIN_VOL_PATH "_ADMIN:/Volumes/"
- static void getvolumeID(BYTE *volumeName)
- {
- char path[zMAX_FULL_NAME];
- Key_t rootKey= 0, fileKey= 0;
- QUAD getInfoMask;
- zInfo_s info;
- STATUS status;
- /* Get the root key */
- if ((status= zRootKey(0, &rootKey)) != zOK)
- {
- consoleprintf("nGetNSSVolumeProperties - Failed to get root key, status: %dn.", (int) status);
- goto exit;
- }
- /*
- Get the file key. This is the key to the volume object in the
- NSS admin volumes directory.
- */
- strxmov(path, (const char *) ADMIN_VOL_PATH, (const char *) volumeName,
- NullS);
- if ((status= zOpen(rootKey, zNSS_TASK, zNSPACE_LONG|zMODE_UTF8,
- (BYTE *) path, zRR_READ_ACCESS, &fileKey)) != zOK)
- {
- consoleprintf("nGetNSSVolumeProperties - Failed to get file, status: %dn.", (int) status);
- goto exit;
- }
- getInfoMask= zGET_IDS | zGET_VOLUME_INFO ;
- if ((status= zGetInfo(fileKey, getInfoMask, sizeof(info),
- zINFO_VERSION_A, &info)) != zOK)
- {
- consoleprintf("nGetNSSVolumeProperties - Failed in zGetInfo, status: %dn.", (int) status);
- goto exit;
- }
- /* Copy the data to global variable */
- datavolid.timeLow= info.vol.volumeID.timeLow;
- datavolid.timeMid= info.vol.volumeID.timeMid;
- datavolid.timeHighAndVersion= info.vol.volumeID.timeHighAndVersion;
- datavolid.clockSeqHighAndReserved= info.vol.volumeID.clockSeqHighAndReserved;
- datavolid.clockSeqLow= info.vol.volumeID.clockSeqLow;
- /* This is guranteed to be 6-byte length (but sizeof() would be better) */
- memcpy(datavolid.node, info.vol.volumeID.node, (unsigned int) 6);
-
- exit:
- if (rootKey)
- zClose(rootKey);
- if (fileKey)
- zClose(fileKey);
- }
- static void init_signals(void)
- {
- int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT};
- for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
- signal(signals[i], kill_server);
- mysql_cb_init(); // initialize callbacks
- }
- static void start_signal_handler(void)
- {
- // Save vm id of this process
- if (!opt_bootstrap)
- create_pid_file();
- // no signal handler
- }
- /*
- Warn if the data is on a Traditional volume
- NOTE
- Already done by mysqld_safe
- */
- static void check_data_home(const char *path)
- {
- }
- #elif defined(__EMX__)
- static void sig_reload(int signo)
- {
- // Flush everything
- reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, NULL);
- signal(signo, SIG_ACK);
- }
- static void sig_kill(int signo)
- {
- if (!kill_in_progress)
- {
- abort_loop=1; // mark abort for threads
- kill_server((void*) signo);
- }
- signal(signo, SIG_ACK);
- }
- static void init_signals(void)
- {
- signal(SIGQUIT, sig_kill);
- signal(SIGKILL, sig_kill);
- signal(SIGTERM, sig_kill);
- signal(SIGINT, sig_kill);
- signal(SIGHUP, sig_reload); // Flush everything
- signal(SIGALRM, SIG_IGN);
- signal(SIGBREAK,SIG_IGN);
- signal_thread = pthread_self();
- }
- static void start_signal_handler(void)
- {}
- static void check_data_home(const char *path)
- {}
- #else /* if ! __WIN__ && ! __EMX__ */
- #ifdef HAVE_LINUXTHREADS
- #define UNSAFE_DEFAULT_LINUX_THREADS 200
- #endif
- extern "C" sig_handler handle_segfault(int sig)
- {
- THD *thd=current_thd;
- /*
- Strictly speaking, one needs a mutex here
- but since we have got SIGSEGV already, things are a mess
- so not having the mutex is not as bad as possibly using a buggy
- mutex - so we keep things simple
- */
- if (segfaulted)
- {
- fprintf(stderr, "Fatal signal %d while backtracingn", sig);
- exit(1);
- }
- segfaulted = 1;
- fprintf(stderr,"
- mysqld got signal %d;n
- This could be because you hit a bug. It is also possible that this binaryn
- or one of the libraries it was linked against is corrupt, improperly built,n
- or misconfigured. This error can also be caused by malfunctioning hardware.n",
- sig);
- fprintf(stderr, "
- We will try our best to scrape up some info that will hopefully help diagnosen
- the problem, but since we have already crashed, something is definitely wrongn
- and this may fail.nn");
- fprintf(stderr, "key_buffer_size=%lun",
- (ulong) dflt_key_cache->key_cache_mem_size);
- fprintf(stderr, "read_buffer_size=%ldn", global_system_variables.read_buff_size);
- fprintf(stderr, "max_used_connections=%ldn", max_used_connections);
- fprintf(stderr, "max_connections=%ldn", max_connections);
- fprintf(stderr, "threads_connected=%dn", thread_count);
- fprintf(stderr, "It is possible that mysqld could use up to n
- key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld Kn
- bytes of memoryn", ((ulong) dflt_key_cache->key_cache_mem_size +
- (global_system_variables.read_buff_size +
- global_system_variables.sortbuff_size) *
- max_connections)/ 1024);
- fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.nn");
- #if defined(HAVE_LINUXTHREADS)
- if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
- {
- fprintf(stderr, "
- You seem to be running 32-bit Linux and have %d concurrent connections.n
- If you have not changed STACK_SIZE in LinuxThreads and built the binary n
- yourself, LinuxThreads is quite likely to steal a part of the global heap forn
- the thread stack. Please read http://www.mysql.com/doc/en/Linux.htmlnn",
- thread_count);
- }
- #endif /* HAVE_LINUXTHREADS */
- #ifdef HAVE_STACKTRACE
- if (!(test_flags & TEST_NO_STACKTRACE))
- {
- fprintf(stderr,"thd=%pn",thd);
- print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
- thread_stack);
- }
- if (thd)
- {
- fprintf(stderr, "Trying to get some variables.n
- Some pointers may be invalid and cause the dump to abort...n");
- safe_print_str("thd->query", thd->query, 1024);
- fprintf(stderr, "thd->thread_id=%ldn", thd->thread_id);
- }
- fprintf(stderr, "
- The manual page at http://www.mysql.com/doc/en/Crashing.html containsn
- information that should help you find out what is causing the crash.n");
- fflush(stderr);
- #endif /* HAVE_STACKTRACE */
- #ifdef HAVE_INITGROUPS
- if (calling_initgroups)
- fprintf(stderr, "n
- This crash occured while the server was calling initgroups(). This isn
- often due to the use of a mysqld that is statically linked against glibcn
- and configured to use LDAP in /etc/nsswitch.conf. You will need to eithern
- upgrade to a version of glibc that does not have this problem (2.3.4 orn
- later when used with nscd), disable LDAP in your nsswitch.conf, or use an
- mysqld that is not statically linked.n");
- #endif
- if (test_flags & TEST_CORE_ON_SIGNAL)
- {
- fprintf(stderr, "Writing a core filen");
- fflush(stderr);
- write_core(sig);
- }
- exit(1);
- }
- #ifndef SA_RESETHAND
- #define SA_RESETHAND 0
- #endif
- #ifndef SA_NODEFER
- #define SA_NODEFER 0
- #endif
- static void init_signals(void)
- {
- sigset_t set;
- struct sigaction sa;
- DBUG_ENTER("init_signals");
- if (test_flags & TEST_SIGINT)
- my_sigset(THR_KILL_SIGNAL,end_thread_signal);
- my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
- if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
- {
- sa.sa_flags = SA_RESETHAND | SA_NODEFER;
- sigemptyset(&sa.sa_mask);
- sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
- init_stacktrace();
- #if defined(__amiga__)
- sa.sa_handler=(void(*)())handle_segfault;
- #else
- sa.sa_handler=handle_segfault;
- #endif
- sigaction(SIGSEGV, &sa, NULL);
- sigaction(SIGABRT, &sa, NULL);
- #ifdef SIGBUS
- sigaction(SIGBUS, &sa, NULL);
- #endif
- sigaction(SIGILL, &sa, NULL);
- sigaction(SIGFPE, &sa, NULL);
- }
- #ifdef HAVE_GETRLIMIT
- if (test_flags & TEST_CORE_ON_SIGNAL)
- {
- /* Change limits so that we will get a core file */
- STRUCT_RLIMIT rl;
- rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
- if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
- sql_print_warning("setrlimit could not change the size of core files to 'infinity'; We may not be able to generate a core file on signals");
- }
- #endif
- (void) sigemptyset(&set);
- my_sigset(SIGPIPE,SIG_IGN);
- sigaddset(&set,SIGPIPE);
- sigaddset(&set,SIGINT);
- #ifndef IGNORE_SIGHUP_SIGQUIT
- sigaddset(&set,SIGQUIT);
- sigaddset(&set,SIGHUP);
- #endif
- sigaddset(&set,SIGTERM);
- /* Fix signals if blocked by parents (can happen on Mac OS X) */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = print_signal_warning;
- sigaction(SIGTERM, &sa, (struct sigaction*) 0);
- sa.sa_flags = 0;
- sa.sa_handler = print_signal_warning;
- sigaction(SIGHUP, &sa, (struct sigaction*) 0);
- #ifdef SIGTSTP
- sigaddset(&set,SIGTSTP);
- #endif
- sigaddset(&set,THR_SERVER_ALARM);
- if (test_flags & TEST_SIGINT)
- sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
- sigdelset(&set,THR_CLIENT_ALARM); // For alarms
- sigprocmask(SIG_SETMASK,&set,NULL);
- pthread_sigmask(SIG_SETMASK,&set,NULL);
- DBUG_VOID_RETURN;
- }
- #ifndef EMBEDDED_LIBRARY
- static void start_signal_handler(void)
- {
- int error;
- pthread_attr_t thr_attr;
- DBUG_ENTER("start_signal_handler");
- (void) pthread_attr_init(&thr_attr);
- #if !defined(HAVE_DEC_3_2_THREADS)
- pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
- (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
- pthread_attr_setstacksize(&thr_attr,thread_stack);
- #endif
- (void) pthread_mutex_lock(&LOCK_thread_count);
- if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
- {
- sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
- error,errno);
- exit(1);
- }
- (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- pthread_mutex_unlock(&LOCK_thread_count);
- (void) pthread_attr_destroy(&thr_attr);
- DBUG_VOID_RETURN;
- }
- /* This threads handles all signals and alarms */
- /* ARGSUSED */
- extern "C" void *signal_hand(void *arg __attribute__((unused)))
- {
- sigset_t set;
- int sig;
- my_thread_init(); // Init new thread
- DBUG_ENTER("signal_hand");
- signal_thread_in_use= 1;
- /*
- Setup alarm handler
- This should actually be '+ max_number_of_slaves' instead of +10,
- but the +10 should be quite safe.
- */
- init_thr_alarm(max_connections +
- global_system_variables.max_insert_delayed_threads + 10);
- #if SIGINT != THR_KILL_SIGNAL
- if (test_flags & TEST_SIGINT)
- {
- (void) sigemptyset(&set); // Setup up SIGINT for debug
- (void) sigaddset(&set,SIGINT); // For debugging
- (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
- }
- #endif
- (void) sigemptyset(&set); // Setup up SIGINT for debug
- #ifdef USE_ONE_SIGNAL_HAND
- (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
- #endif
- #ifndef IGNORE_SIGHUP_SIGQUIT
- (void) sigaddset(&set,SIGQUIT);
- #if THR_CLIENT_ALARM != SIGHUP
- (void) sigaddset(&set,SIGHUP);
- #endif
- #endif
- (void) sigaddset(&set,SIGTERM);
- (void) sigaddset(&set,SIGTSTP);
- /* Save pid to this process (or thread on Linux) */
- if (!opt_bootstrap)
- create_pid_file();
- #ifdef HAVE_STACK_TRACE_ON_SEGV
- if (opt_do_pstack)
- {
- sprintf(pstack_file_name,"mysqld-%lu-%%d-%%d.backtrace", (ulong)getpid());
- pstack_install_segv_action(pstack_file_name);
- }
- #endif /* HAVE_STACK_TRACE_ON_SEGV */
- /*
- signal to start_signal_handler that we are ready
- This works by waiting for start_signal_handler to free mutex,
- after which we signal it that we are ready.
- At this pointer there is no other threads running, so there
- should not be any other pthread_cond_signal() calls.
- */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- (void) pthread_cond_broadcast(&COND_thread_count);
- (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
- for (;;)
- {
- int error; // Used when debugging
- if (shutdown_in_progress && !abort_loop)
- {
- sig= SIGTERM;
- error=0;
- }
- else
- while ((error=my_sigwait(&set,&sig)) == EINTR) ;
- if (cleanup_done)
- {
- DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
- my_thread_end();
- signal_thread_in_use= 0;
- pthread_exit(0); // Safety
- }
- switch (sig) {
- case SIGTERM:
- case SIGQUIT:
- case SIGKILL:
- #ifdef EXTRA_DEBUG
- sql_print_information("Got signal %d to shutdown mysqld",sig);
- #endif
- DBUG_PRINT("info",("Got signal: %d abort_loop: %d",sig,abort_loop));
- if (!abort_loop)
- {
- abort_loop=1; // mark abort for threads
- #ifdef USE_ONE_SIGNAL_HAND
- pthread_t tmp;
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
- if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
- (void*) sig))
- sql_print_error("Can't create thread to kill server");
- #else
- kill_server((void*) sig); // MIT THREAD has a alarm thread
- #endif
- }
- break;
- case SIGHUP:
- if (!abort_loop)
- {
- mysql_print_status((THD*) 0); // Print some debug info
- reload_acl_and_cache((THD*) 0,
- (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
- REFRESH_STATUS | REFRESH_GRANT |
- REFRESH_THREADS | REFRESH_HOSTS),
- (TABLE_LIST*) 0, NULL); // Flush logs
- }
- break;
- #ifdef USE_ONE_SIGNAL_HAND
- case THR_SERVER_ALARM:
- process_alarm(sig); // Trigger alarms.
- break;
- #endif
- default:
- #ifdef EXTRA_DEBUG
- sql_print_warning("Got signal: %d error: %d",sig,error); /* purecov: tested */
- #endif
- break; /* purecov: tested */
- }
- }
- return(0); /* purecov: deadcode */
- }
- #endif /*!EMBEDDED_LIBRARY*/
- static void check_data_home(const char *path)
- {}
- #endif /* __WIN__*/
- /*
- All global error messages are sent here where the first one is stored for
- the client
- */
- /* ARGSUSED */
- extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
- {
- THD *thd;
- DBUG_ENTER("my_message_sql");
- DBUG_PRINT("error", ("Message: '%s'", str));
- if ((thd= current_thd))
- {
- /*
- thd->lex->current_select == 0 if lex structure is not inited
- (not query command (COM_QUERY))
- */
- if (thd->lex->current_select &&
- thd->lex->current_select->no_error && !thd->is_fatal_error)
- {
- DBUG_PRINT("error", ("Error converted to warning: current_select: no_error %d fatal_error: %d",
- (thd->lex->current_select ?
- thd->lex->current_select->no_error : 0),
- (int) thd->is_fatal_error));
-
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
- }
- else
- {
- NET *net= &thd->net;
- net->report_error= 1;
- if (!net->last_error[0]) // Return only first message
- {
- strmake(net->last_error, str, sizeof(net->last_error)-1);
- net->last_errno= error ? error : ER_UNKNOWN_ERROR;
- }
- }
- }
- if (!thd || MyFlags & ME_NOREFRESH)
- sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
- DBUG_RETURN(0);
- }
- #ifdef __WIN__
- struct utsname
- {
- char nodename[FN_REFLEN];
- };
- int uname(struct utsname *a)
- {
- return -1;
- }
- extern "C" pthread_handler_decl(handle_shutdown,arg)
- {
- MSG msg;
- my_thread_init();
- /* this call should create the message queue for this thread */
- PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
- #if !defined(EMBEDDED_LIBRARY)
- if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
- #endif /* EMBEDDED_LIBRARY */
- kill_server(MYSQL_KILL_SIGNAL);
- return 0;
- }
- int STDCALL handle_kill(ulong ctrl_type)
- {
- if (ctrl_type == CTRL_CLOSE_EVENT ||
- ctrl_type == CTRL_SHUTDOWN_EVENT)
- {
- kill_server(MYSQL_KILL_SIGNAL);
- return TRUE;
- }
- return FALSE;
- }
- #endif
- #ifdef OS2
- extern "C" pthread_handler_decl(handle_shutdown,arg)
- {
- my_thread_init();
- // wait semaphore
- pthread_cond_wait( &eventShutdown, NULL);
- // close semaphore and kill server
- pthread_cond_destroy( &eventShutdown);
- /*
- Exit main loop on main thread, so kill will be done from
- main thread (this is thread 2)
- */
- abort_loop = 1;
- // unblock select()
- so_cancel(ip_sock);
- so_cancel(unix_sock);
- return 0;
- }
- #endif
- const char *load_default_groups[]= {
- #ifdef HAVE_NDBCLUSTER_DB
- "mysql_cluster",
- #endif
- "mysqld","server",MYSQL_BASE_VERSION,0,0};
- static const int load_default_groups_sz=
- sizeof(load_default_groups)/sizeof(load_default_groups[0]);
- bool open_log(MYSQL_LOG *log, const char *hostname,
- const char *opt_name, const char *extension,
- const char *index_file_name,
- enum_log_type type, bool read_append,
- bool no_auto_events, ulong max_size)
- {
- char tmp[FN_REFLEN];
- if (!opt_name || !opt_name[0])
- {
- /*
- TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,hostname,FN_REFLEN-5);
- strmov(fn_ext(tmp),extension);
- opt_name=tmp;
- }
- // get rid of extension if the log is binary to avoid problems
- if (type == LOG_BIN)
- {
- char *p = fn_ext(opt_name);
- uint length=(uint) (p-opt_name);
- strmake(tmp,opt_name,min(length,FN_REFLEN));
- opt_name=tmp;
- }
- return log->open(opt_name, type, 0, index_file_name,
- (read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
- no_auto_events, max_size);
- }
- /*
- Initialize one of the global date/time format variables
- SYNOPSIS
- init_global_datetime_format()
- format_type What kind of format should be supported
- var_ptr Pointer to variable that should be updated
-
- NOTES
- The default value is taken from either opt_date_time_formats[] or
- the ISO format (ANSI SQL)
- RETURN
- 0 ok
- 1 error
- */
- bool init_global_datetime_format(timestamp_type format_type,
- DATE_TIME_FORMAT **var_ptr)
- {
- /* Get command line option */
- const char *str= opt_date_time_formats[format_type];
- if (!str) // No specified format
- {
- str= get_date_time_format_str(&known_date_time_formats[ISO_FORMAT],
- format_type);
- /*
- Set the "command line" option to point to the generated string so
- that we can set global formats back to default
- */
- opt_date_time_formats[format_type]= str;
- }
- if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str))))
- {
- fprintf(stderr, "Wrong date/time format specifier: %sn", str);
- return 1;
- }
- return 0;
- }
- static int init_common_variables(const char *conf_file_name, int argc,
- char **argv, const char **groups)
- {
- umask(((~my_umask) & 0666));
- tzset(); // Set tzname
- max_system_variables.pseudo_thread_id= (ulong)~0;
- start_time=time((time_t*) 0);
- if (init_thread_environment())
- return 1;
- mysql_init_variables();
- #ifdef OS2
- {
- // fix timezone for daylight saving
- struct tm *ts = localtime(&start_time);
- if (ts->tm_isdst > 0)
- _timezone -= 3600;
- }
- #endif
- #ifdef HAVE_TZNAME
- {
- struct tm tm_tmp;
- localtime_r(&start_time,&tm_tmp);
- strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
- sizeof(system_time_zone)-1);
- }
- #endif
- /*
- We set SYSTEM time zone as reasonable default and
- also for failure of my_tz_init() and bootstrap mode.
- If user explicitly set time zone with --default-time-zone
- option we will change this value in my_tz_init().
- */
- global_system_variables.time_zone= my_tz_SYSTEM;
-
- /*
- Init mutexes for the global MYSQL_LOG objects.
- As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
- global MYSQL_LOGs in their constructors, because then they would be inited
- before MY_INIT(). So we do it here.
- */
- mysql_log.init_pthread_objects();
- mysql_update_log.init_pthread_objects();
- mysql_slow_log.init_pthread_objects();
- mysql_bin_log.init_pthread_objects();
-
- if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
- strmov(glob_hostname,"mysql");
- strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
- strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
- load_defaults(conf_file_name, groups, &argc, &argv);
- defaults_argv=argv;
- get_options(argc,argv);
- set_server_version();
- DBUG_PRINT("info",("%s Ver %s for %s on %sn",my_progname,
- server_version, SYSTEM_TYPE,MACHINE_TYPE));
- /* connections and databases needs lots of files */
- {
- uint files, wanted_files;
- wanted_files= 10+(uint) max(max_connections*5,
- max_connections+table_cache_size*2);
- set_if_bigger(wanted_files, open_files_limit);
- files= my_set_max_open_files(wanted_files);
- if (files < wanted_files)
- {
- if (!open_files_limit)
- {
- max_connections= (ulong) min((files-10),max_connections);
- table_cache_size= (ulong) max((files-10-max_connections)/2,64);
- DBUG_PRINT("warning",
- ("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
- files, max_connections, table_cache_size));
- if (global_system_variables.log_warnings)
- sql_print_warning("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
- files, max_connections, table_cache_size);
- }
- else if (global_system_variables.log_warnings)
- sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
- }
- open_files_limit= files;
- }
- unireg_init(opt_specialflag); /* Set up extern variabels */
- if (init_errmessage()) /* Read error messages from file */
- return 1;
- init_client_errs();
- lex_init();
- item_init();
- set_var_init();
- mysys_uses_curses=0;
- #ifdef USE_REGEX
- my_regex_init(&my_charset_latin1);
- #endif
- if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
- MY_CS_PRIMARY,
- MYF(MY_WME))))
- return 1;
- if (default_collation_name)
- {
- CHARSET_INFO *default_collation;
- default_collation= get_charset_by_name(default_collation_name, MYF(0));
- if (!default_collation)
- {
- sql_print_error(ER(ER_UNKNOWN_COLLATION), default_collation_name);
- return 1;
- }
- if (!my_charset_same(default_charset_info, default_collation))
- {
- sql_print_error(ER(ER_COLLATION_CHARSET_MISMATCH),
- default_collation_name,
- default_charset_info->csname);
- return 1;
- }
- default_charset_info= default_collation;
- }
- /* Set collactions that depends on the default collation */
- global_system_variables.collation_server= default_charset_info;
- global_system_variables.collation_database= default_charset_info;
- global_system_variables.collation_connection= default_charset_info;
- global_system_variables.character_set_results= default_charset_info;
- global_system_variables.character_set_client= default_charset_info;
- global_system_variables.collation_connection= default_charset_info;
- sys_init_connect.value_length= 0;
- if ((sys_init_connect.value= opt_init_connect))
- sys_init_connect.value_length= strlen(opt_init_connect);
- else
- sys_init_connect.value=my_strdup("",MYF(0));
- sys_init_slave.value_length= 0;
- if ((sys_init_slave.value= opt_init_slave))
- sys_init_slave.value_length= strlen(opt_init_slave);
- else
- sys_init_slave.value=my_strdup("",MYF(0));
- if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
- return 1;
- if (my_dbopt_init())
- return 1;
- /*
- Ensure that lower_case_table_names is set on system where we have case
- insensitive names. If this is not done the users MyISAM tables will
- get corrupted if accesses with names of different case.
- */
- DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
- if (!lower_case_table_names &&
- (lower_case_file_system=
- (test_if_case_insensitive(mysql_real_data_home) == 1)))
- {
- if (lower_case_table_names_used)
- {
- if (global_system_variables.log_warnings)
- sql_print_warning("
- You have forced lower_case_table_names to 0 through a command-line
- option, even though your file system '%s' is case insensitive. This means
- that you can corrupt a MyISAM table by accessing it with different cases.
- You should consider changing lower_case_table_names to 1 or 2",
- mysql_real_data_home);
- }
- else
- {
- if (global_system_variables.log_warnings)
- sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
- lower_case_table_names= 2;
- }
- }
- else if (lower_case_table_names == 2 &&
- !(lower_case_file_system=
- (test_if_case_insensitive(mysql_real_data_home) == 1)))
- {
- if (global_system_variables.log_warnings)
- sql_print_warning("lower_case_table_names was set to 2, even though your "
- "the file system '%s' is case sensitive. Now setting "
- "lower_case_table_names to 0 to avoid future problems.",
- mysql_real_data_home);
- lower_case_table_names= 0;
- }
- /* Reset table_alias_charset, now that lower_case_table_names is set. */
- table_alias_charset= (lower_case_table_names ?
- files_charset_info :
- &my_charset_bin);
- return 0;
- }
- static int init_thread_environment()
- {
- (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
- #ifdef HAVE_OPENSSL
- (void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
- #endif
- (void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
- (void) my_rwlock_init(&LOCK_sys_init_slave, NULL);
- (void) my_rwlock_init(&LOCK_grant, NULL);
- (void) pthread_cond_init(&COND_thread_count,NULL);
- (void) pthread_cond_init(&COND_refresh,NULL);
- (void) pthread_cond_init(&COND_thread_cache,NULL);
- (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
- (void) pthread_cond_init(&COND_manager,NULL);
- #ifdef HAVE_REPLICATION
- (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
- (void) pthread_cond_init(&COND_rpl_status, NULL);
- #endif
- /* Parameter for threads created for connections */
- (void) pthread_attr_init(&connection_attrib);
- (void) pthread_attr_setdetachstate(&connection_attrib,
- PTHREAD_CREATE_DETACHED);
- pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
- if (pthread_key_create(&THR_THD,NULL) ||
- pthread_key_create(&THR_MALLOC,NULL))
- {
- sql_print_error("Can't create thread-keys");
- return 1;
- }
- #ifdef HAVE_OPENSSL
- openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
- sizeof(openssl_lock_t));
- for (int i= 0; i < CRYPTO_num_locks(); ++i)
- (void) my_rwlock_init(&openssl_stdlocks[i].lock, NULL);
- CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
- CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
- CRYPTO_set_dynlock_lock_callback(openssl_lock);
- CRYPTO_set_locking_callback(openssl_lock_function);
- CRYPTO_set_id_callback(openssl_id_function);
- #endif
- return 0;
- }
- #ifdef HAVE_OPENSSL
- static unsigned long openssl_id_function()
- {
- return (unsigned long) pthread_self();
- }
- static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
- {
- openssl_lock_t *lock= new openssl_lock_t;
- my_rwlock_init(&lock->lock, NULL);
- return lock;
- }
- static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
- int line)
- {
- rwlock_destroy(&lock->lock);
- delete lock;
- }
- static void openssl_lock_function(int mode, int n, const char *file, int line)
- {
- if (n < 0 || n > CRYPTO_num_locks())
- {
- /* Lock number out of bounds. */
- sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
- abort();
- }
- openssl_lock(mode, &openssl_stdlocks[n], file, line);
- }
- static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
- int line)
- {
- int err;
- char const *what;
- switch (mode) {
- case CRYPTO_LOCK|CRYPTO_READ:
- what = "read lock";
- err = rw_rdlock(&lock->lock);
- break;
- case CRYPTO_LOCK|CRYPTO_WRITE:
- what = "write lock";
- err = rw_wrlock(&lock->lock);
- break;
- case CRYPTO_UNLOCK|CRYPTO_READ:
- case CRYPTO_UNLOCK|CRYPTO_WRITE:
- what = "unlock";
- err = rw_unlock(&lock->lock);
- break;
- default:
- /* Unknown locking mode. */
- sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
- abort();
- }
- if (err)
- {
- sql_print_error("Fatal: can't %s OpenSSL %s lock", what);
- abort();
- }
- }
- #endif /* HAVE_OPENSSL */
- static void init_ssl()
- {
- #ifdef HAVE_OPENSSL
- if (opt_use_ssl)
- {
- /* having ssl_acceptor_fd != 0 signals the use of SSL */
- ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
- opt_ssl_ca, opt_ssl_capath,
- opt_ssl_cipher);
- DBUG_PRINT("info",("ssl_acceptor_fd: %lx", (long) ssl_acceptor_fd));
- if (!ssl_acceptor_fd)
- opt_use_ssl = 0;
- }
- if (des_key_file)
- load_des_key_file(des_key_file);
- #endif /* HAVE_OPENSSL */
- }
- static int init_server_components()
- {
- DBUG_ENTER("init_server_components");
- if (table_cache_init() || hostname_cache_init())
- unireg_abort(1);
- query_cache_result_size_limit(query_cache_limit);
- query_cache_set_min_res_unit(query_cache_min_res_unit);
- query_cache_init();
- query_cache_resize(query_cache_size);
- randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
- reset_floating_point_exceptions();
- init_thr_lock();
- #ifdef HAVE_REPLICATION
- init_slave_list();
- #endif
- /* Setup log files */
- if (opt_log)
- open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
- LOG_NORMAL, 0, 0, 0);
- if (opt_update_log)
- {
- open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
- NullS, LOG_NEW, 0, 0, 0);
- using_update_log=1;
- }
- if (opt_slow_log)
- open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
- NullS, LOG_NORMAL, 0, 0, 0);
- if (opt_bin_log)
- {
- /* If we fail to open binlog, it's going to hinder our recovery, so die */
- if (open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
- opt_binlog_index_name, LOG_BIN, 0, 0, max_binlog_size))
- unireg_abort(1);
- using_update_log=1;
- #ifdef HAVE_REPLICATION
- if (expire_logs_days)
- {
- long purge_time= time(0) - expire_logs_days*24*60*60;
- if (purge_time >= 0)
- mysql_bin_log.purge_logs_before_date(purge_time);
- }
- #endif
- }
- else if (opt_log_slave_updates)
- {
- sql_print_warning("
- you need to use --log-bin to make --log-slave-updates work.
- Now disabling --log-slave-updates.");
- }
- #ifdef HAVE_REPLICATION
- if (opt_log_slave_updates && replicate_same_server_id)
- {
- sql_print_error("
- using --replicate-same-server-id in conjunction with
- --log-slave-updates is impossible, it would lead to infinite loops in this
- server.");
- unireg_abort(1);
- }
- #endif
- if (opt_error_log)
- {
- if (!log_error_file_ptr[0])
- fn_format(log_error_file, glob_hostname, mysql_data_home, ".err",
- MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
- else
- fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
- MY_UNPACK_FILENAME | MY_SAFE_PATH);
- if (!log_error_file[0])
- opt_error_log= 1; // Too long file name
- else
- {
- #ifndef EMBEDDED_LIBRARY
- if (freopen(log_error_file, "a+", stdout))
- #endif
- stderror_file= freopen(log_error_file, "a+", stderr);
- }
- }
- if (opt_innodb_safe_binlog)
- {
- if (have_innodb != SHOW_OPTION_YES)
- sql_print_warning("--innodb-safe-binlog is meaningful only if "
- "the InnoDB storage engine is enabled in the server.");
- #ifdef HAVE_INNOBASE_DB
- if (innobase_flush_log_at_trx_commit != 1)
- {
- sql_print_warning("--innodb-safe-binlog is meaningful only if "
- "innodb_flush_log_at_trx_commit is 1; now setting it "
- "to 1.");
- innobase_flush_log_at_trx_commit= 1;
- }
- if (innobase_unix_file_flush_method)
- {
- /*
- This option has so many values that it's hard to know which value is
- good (especially "littlesync", and on Windows... see
- srv/srv0start.c).
- */
- sql_print_warning("--innodb-safe-binlog requires that "
- "the innodb_flush_method actually synchronizes the "
- "InnoDB log to disk; it is your responsibility "
- "to verify that the method you chose does it.");
- }
- if (sync_binlog_period != 1)
- {
- sql_print_warning("--innodb-safe-binlog is meaningful only if "
- "the global sync_binlog variable is 1; now setting it "
- "to 1.");
- sync_binlog_period= 1;
- }
- #endif
- }
- if (ha_init())
- {
- sql_print_error("Can't init databases");
- unireg_abort(1);
- }
- if (opt_myisam_log)
- (void) mi_log(1);
- /*
- Now that InnoDB is initialized, we can know the last good binlog position
- and cut the binlog if needed. This function does nothing if there was no
- crash recovery by InnoDB.
- */
- if (opt_innodb_safe_binlog)
- {
- /* not fatal if fails (but print errors) */
- mysql_bin_log.cut_spurious_tail();
- }
- mysql_bin_log.report_pos_in_innodb();
- /* call ha_init_key_cache() on all key caches to init them */
- process_key_caches(&ha_init_key_cache);
- #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
- if (locked_in_memory && !getuid())
- {
- if (setreuid((uid_t)-1, 0) == -1)
- { // this should never happen
- sql_perror("setreuid");
- unireg_abort(1);
- }
- if (mlockall(MCL_CURRENT))
- {
- if (global_system_variables.log_warnings)
- sql_print_warning("Failed to lock memory. Errno: %dn",errno);
- locked_in_memory= 0;
- }
- if (user_info)
- set_user(mysqld_user, user_info);
- }
- else
- #endif
- locked_in_memory=0;
- ft_init_stopwords();
- init_max_user_conn();
- init_update_queries();
- DBUG_RETURN(0);
- }
- static void create_maintenance_thread()
- {
- if (
- #ifdef HAVE_BERKELEY_DB
- (have_berkeley_db == SHOW_OPTION_YES) ||
- #endif
- (flush_time && flush_time != ~(ulong) 0L))
- {
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
- sql_print_warning("Can't create thread to manage maintenance");
- }
- }
- static void create_shutdown_thread()
- {
- #if !defined(EMBEDDED_LIBRARY)
- #ifdef __WIN__
- hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
- sql_print_warning("Can't create thread to handle shutdown requests");
- // On "Stop Service" we have to do regular shutdown
- Service.SetShutdownEvent(hEventShutdown);
- #endif
- #ifdef OS2
- pthread_cond_init(&eventShutdown, NULL);
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
- sql_print_warning("Can't create thread to handle shutdown requests");
- #endif
- #endif // EMBEDDED_LIBRARY
- }
- #if defined(__NT__) || defined(HAVE_SMEM)
- static void handle_connections_methods()
- {
- pthread_t hThread;
- DBUG_ENTER("handle_connections_methods");
- #ifdef __NT__
- if (hPipe == INVALID_HANDLE_VALUE &&
- (!have_tcpip || opt_disable_networking) &&
- !opt_enable_shared_memory)
- {
- sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
- unireg_abort(1); // Will not return
- }
- #endif
- pthread_mutex_lock(&LOCK_thread_count);
- (void) pthread_cond_init(&COND_handler_count,NULL);
- handler_count=0;
- #ifdef __NT__
- if (hPipe != INVALID_HANDLE_VALUE)
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_namedpipes, 0))
- {
- sql_print_warning("Can't create thread to handle named pipes");
- handler_count--;
- }
- }
- #endif /* __NT__ */
- if (have_tcpip && !opt_disable_networking)
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_sockets, 0))
- {
- sql_print_warning("Can't create thread to handle TCP/IP");
- handler_count--;
- }
- }
- #ifdef HAVE_SMEM
- if (opt_enable_shared_memory)
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_shared_memory, 0))
- {
- sql_print_warning("Can't create thread to handle shared memory");
- handler_count--;
- }
- }
- #endif
- while (handler_count > 0)
- pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
- pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_VOID_RETURN;
- }
- void decrement_handler_count()
- {
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
- }
- #else
- #define decrement_handler_count()
- #endif /* defined(__NT__) || defined(HAVE_SMEM) */
- #ifndef EMBEDDED_LIBRARY
- #ifdef __WIN__
- int win_main(int argc, char **argv)
- #else
- int main(int argc, char **argv)
- #endif
- {
- DEBUGGER_OFF;
- MY_INIT(argv[0]); // init my_sys library & pthreads
- #ifdef _CUSTOMSTARTUPCONFIG_
- if (_cust_check_startup())
- {
- / * _cust_check_startup will report startup failure error * /
- exit( 1 );
- }
- #endif
- if (init_common_variables(MYSQL_CONFIG_NAME,
- argc, argv, load_default_groups))
- unireg_abort(1); // Will do exit
- init_signals();
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
- pthread_attr_setstacksize(&connection_attrib,thread_stack);
- #ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
- {
- /* Retrieve used stack size; Needed for checking stack overflows */
- size_t stack_size= 0;
- pthread_attr_getstacksize(&connection_attrib, &stack_size);
- /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
- if (stack_size && stack_size < thread_stack)
- {
- if (global_system_variables.log_warnings)
- sql_print_warning("Asked for %ld thread stack, but got %ld",
- thread_stack, stack_size);
- thread_stack= stack_size;
- }
- }
- #endif
- thread_stack_min=thread_stack - STACK_MIN_SIZE;
- (void) thr_setconcurrency(concurrency); // 10 by default
- select_thread=pthread_self();
- select_thread_in_use=1;
- init_ssl();
- #ifdef HAVE_LIBWRAP
- libwrapName= my_progname+dirname_length(my_progname);
- openlog(libwrapName, LOG_PID, LOG_AUTH);
- #endif
- /*
- We have enough space for fiddling with the argv, continue
- */
- check_data_home(mysql_real_data_home);
- if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
- {
- unireg_abort(1); /* purecov: inspected */
- }
- mysql_data_home= mysql_data_home_buff;
- mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
- mysql_data_home[1]=0;
- server_init();
- if (opt_bin_log && !server_id)
- {
- server_id= !master_host ? 1 : 2;
- #ifdef EXTRA_DEBUG
- switch (server_id) {
- case 1:
- sql_print_warning("
- You have enabled the binary log, but you haven't set server-id to
- a non-zero value: we force server id to 1; updates will be logged to the
- binary log, but connections from slaves will not be accepted.");
- break;
- case 2:
- sql_print_warning("
- You should set server-id to a non-0 value if master_host is set;
- we force server id to 2, but this MySQL server will not act as a slave.");
- break;
- }
- #endif
- }
- if (init_server_components())
- exit(1);
- #ifdef __WIN__
- if (!opt_console)
- {
- freopen(log_error_file,"a+",stdout);
- freopen(log_error_file,"a+",stderr);
- FreeConsole(); // Remove window
- }
- #endif
- /*
- init signals & alarm
- After this we can't quit by a simple unireg_abort
- */
- error_handler_hook = my_message_sql;
- start_signal_handler(); // Creates pidfile
- if (acl_init(opt_noacl) ||
- my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
- {
- abort_loop=1;
- select_thread_in_use=0;
- #ifndef __NETWARE__
- (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
- #endif /* __NETWARE__ */
-
- if (!opt_bootstrap)
- (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
- if (unix_sock != INVALID_SOCKET)
- unlink(mysqld_unix_port);
- exit(1);
- }
- if (!opt_noacl)
- (void) grant_init();
- #ifdef HAVE_DLOPEN
- if (!opt_noacl)
- udf_init();
- #endif
- if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
- opt_skip_slave_start= 1;
- /*
- init_slave() must be called after the thread keys are created.
- Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
- places) assume that active_mi != 0, so let's fail if it's 0 (out of
- memory); a message has already been printed.
- */
- if (init_slave() && !active_mi)
- {
- end_thr_alarm(1); // Don't allow alarms
- unireg_abort(1);
- }
- if (opt_bootstrap)
- {
- select_thread_in_use= 0; // Allow 'kill' to work
- int error= bootstrap(stdin);
- end_thr_alarm(1); // Don't allow alarms
- unireg_abort(error ? 1 : 0);
- }
- if (opt_init_file)
- {
- if (read_init_file(opt_init_file))
- {
- end_thr_alarm(1); // Don't allow alarms
- unireg_abort(1);
- }
- }
- create_shutdown_thread();
- create_maintenance_thread();
- printf(ER(ER_READY),my_progname,server_version,
- ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port),
- mysqld_port, "");
- if (MYSQL_COMPILATION_COMMENT[0] != ' ')
- fputs(" " MYSQL_COMPILATION_COMMENT, stdout);
- putchar('n');
- fflush(stdout);
- #if defined(__NT__) || defined(HAVE_SMEM)
- handle_connections_methods();
- #else
- #ifdef __WIN__
- if ( !have_tcpip || opt_disable_networking)
- {
- sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
- unireg_abort(1);
- }
- #endif
- handle_connections_sockets(0);
- #endif /* __NT__ */
- /* (void) pthread_attr_destroy(&connection_attrib); */
-
- DBUG_PRINT("quit",("Exiting main thread"));
- #ifndef __WIN__
- #ifdef EXTRA_DEBUG2
- sql_print_error("Before Lock_thread_count");
- #endif
- (void) pthread_mutex_lock(&LOCK_thread_count);
- DBUG_PRINT("quit", ("Got thread_count mutex"));
- select_thread_in_use=0; // For close_connections
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- (void) pthread_cond_broadcast(&COND_thread_count);
- #ifdef EXTRA_DEBUG2
- sql_print_error("After lock_thread_count");
- #endif
- #endif /* __WIN__ */
- /* Wait until cleanup is done */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (!ready_to_exit)
- pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
- if (Service.IsNT() && start_mode)
- Service.Stop();
- else
- {
- Service.SetShutdownEvent(0);
- if (hEventShutdown)
- CloseHandle(hEventShutdown);
- }
- #endif
- wait_for_signal_thread_to_end();
- clean_up_mutexes();
- my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
-
- exit(0);
- return(0); /* purecov: deadcode */
- }
- #endif /* EMBEDDED_LIBRARY */
- /****************************************************************************
- Main and thread entry function for Win32
- (all this is needed only to run mysqld as a service on WinNT)
- ****************************************************************************/
- #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
- int mysql_service(void *p)
- {
- if (use_opt_args)
- win_main(opt_argc, opt_argv);
- else
- win_main(Service.my_argc, Service.my_argv);
- return 0;
- }
- /* Quote string if it contains space, else copy */
- static char *add_quoted_string(char *to, const char *from, char *to_end)
- {
- uint length= (uint) (to_end-to);
- if (!strchr(from, ' '))
- return strnmov(to, from, length);
- return strxnmov(to, length, """, from, """, NullS);
- }
- /*
- Handle basic handling of services, like installation and removal
- SYNOPSIS
- default_service_handling()
- argv Pointer to argument list
- servicename Internal name of service
- displayname Display name of service (in taskbar ?)
- file_path Path to this program
- startup_option Startup option to mysqld
- RETURN VALUES
- 0 option handled
- 1 Could not handle option
- */
- static bool
- default_service_handling(char **argv,
- const char *servicename,
- const char *displayname,
- const char *file_path,
- const char *extra_opt)
- {
- char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
- end= path_and_service + sizeof(path_and_service)-3;
- /* We have to quote filename if it contains spaces */
- pos= add_quoted_string(path_and_service, file_path, end);
- if (*extra_opt)
- {
- /* Add (possible quoted) option after file_path */
- *pos++= ' ';
- pos= add_quoted_string(pos, extra_opt, end);
- }
- /* We must have servicename last */
- *pos++= ' ';
- (void) add_quoted_string(pos, servicename, end);
- if (Service.got_service_option(argv, "install"))
- {
- Service.Install(1, servicename, displayname, path_and_service);
- return 0;
- }
- if (Service.got_service_option(argv, "install-manual"))
- {
- Service.Install(0, servicename, displayname, path_and_service);
- return 0;
- }
- if (Service.got_service_option(argv, "remove"))
- {
- Service.Remove(servicename);
- return 0;
- }
- return 1;
- }
- int main(int argc, char **argv)
- {
- /* When several instances are running on the same machine, we
- need to have an unique named hEventShudown through the
- application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
- */
- int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
- "MySQLShutdown"), 10);
-
- /* Must be initialized early for comparison of service name */
- system_charset_info= &my_charset_utf8_general_ci;
- if (Service.GetOS()) /* true NT family */
- {
- char file_path[FN_REFLEN];
- my_path(file_path, argv[0], ""); /* Find name in path */
- fn_format(file_path,argv[0],file_path,"",
- MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
- if (argc == 2)
- {
- if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
- file_path, ""))
- return 0;
- if (Service.IsService(argv[1])) /* Start an optional service */
- {
- /*
- Only add the service name to the groups read from the config file
- if it's not "MySQL". (The default service name should be 'mysqld'
- but we started a bad tradition by calling it MySQL from the start
- and we are now stuck with it.
- */
- if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
- load_default_groups[load_default_groups_sz-2]= argv[1];
- start_mode= 1;
- Service.Init(argv[1], mysql_service);
- return 0;
- }
- }
- else if (argc == 3) /* install or remove any optional service */
- {
- if (!default_service_handling(argv, argv[2], argv[2], file_path, ""))
- return 0;
- if (Service.IsService(argv[2]))
- {
- /*
- mysqld was started as
- mysqld --defaults-file=my_pathmy.ini service-name
- */
- use_opt_args=1;
- opt_argc= 2; // Skip service-name
- opt_argv=argv;
- start_mode= 1;
- if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
- load_default_groups[load_default_groups_sz-2]= argv[2];
- Service.Init(argv[2], mysql_service);
- return 0;
- }
- }
- else if (argc == 4)
- {
- /*
- Install an optional service with optional config file
- mysqld --install-manual mysqldopt --defaults-file=c:miguelmy.ini
- */
- if (!default_service_handling(argv, argv[2], argv[2], file_path,
- argv[3]))
- return 0;
- }
- else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
- {
- /* start the default service */
- start_mode= 1;
- Service.Init(MYSQL_SERVICENAME, mysql_service);
- return 0;
- }
- }
- /* Start as standalone server */
- Service.my_argc=argc;
- Service.my_argv=argv;
- mysql_service(NULL);
- return 0;
- }
- #endif
- /*
- Execute all commands from a file. Used by the mysql_install_db script to
- create MySQL privilege tables without having to start a full MySQL server.
- */
- static int bootstrap(FILE *file)
- {
- int error= 0;
- DBUG_ENTER("bootstrap");
- THD *thd= new THD;
- thd->bootstrap=1;
- my_net_init(&thd->net,(st_vio*) 0);
- thd->max_client_packet_length= thd->net.max_packet;
- thd->master_access= ~(ulong)0;
- thd->thread_id=thread_id++;
- thread_count++;