mysqld.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:243k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000-2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include "mysql_priv.h"
  14. #include <m_ctype.h>
  15. #include <my_dir.h>
  16. #include "slave.h"
  17. #include "sql_repl.h"
  18. #include "repl_failsafe.h"
  19. #include "stacktrace.h"
  20. #include "mysqld_suffix.h"
  21. #ifdef HAVE_BERKELEY_DB
  22. #include "ha_berkeley.h"
  23. #endif
  24. #ifdef HAVE_INNOBASE_DB
  25. #include "ha_innodb.h"
  26. #endif
  27. #include "ha_myisam.h"
  28. #ifdef HAVE_ISAM
  29. #include "ha_isam.h"
  30. #endif
  31. #ifdef HAVE_NDBCLUSTER_DB
  32. #include "ha_ndbcluster.h"
  33. #endif
  34. #ifdef HAVE_INNOBASE_DB
  35. #define OPT_INNODB_DEFAULT 1
  36. #else
  37. #define OPT_INNODB_DEFAULT 0
  38. #endif
  39. #ifdef HAVE_BERKLEY_DB
  40. #define OPT_BDB_DEFAULT 1
  41. #else
  42. #define OPT_BDB_DEFAULT 0
  43. #endif
  44. #ifdef HAVE_ISAM_DB
  45. #define OPT_ISAM_DEFAULT 1
  46. #else
  47. #define OPT_ISAM_DEFAULT 0
  48. #endif
  49. #ifdef HAVE_NDBCLUSTER_DB
  50. #define OPT_NDBCLUSTER_DEFAULT 0
  51. #if defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
  52. #define OPT_NDB_SHM_DEFAULT 1
  53. #else
  54. #define OPT_NDB_SHM_DEFAULT 0
  55. #endif
  56. #else
  57. #define OPT_NDBCLUSTER_DEFAULT 0
  58. #endif
  59. #include <nisam.h>
  60. #include <thr_alarm.h>
  61. #include <ft_global.h>
  62. #include <errmsg.h>
  63. #define mysqld_charset &my_charset_latin1
  64. #ifndef DBUG_OFF
  65. #define ONE_THREAD
  66. #endif
  67. #ifdef HAVE_purify
  68. #define IF_PURIFY(A,B) (A)
  69. #else
  70. #define IF_PURIFY(A,B) (B)
  71. #endif
  72. #ifndef INADDR_NONE
  73. #define INADDR_NONE -1 // Error value from inet_addr
  74. #endif
  75. /* stack traces are only supported on linux intel */
  76. #if defined(__linux__)  && defined(__i386__) && defined(USE_PSTACK)
  77. #define HAVE_STACK_TRACE_ON_SEGV
  78. #include "../pstack/pstack.h"
  79. char pstack_file_name[80];
  80. #endif /* __linux__ */
  81. /* We have HAVE_purify below as this speeds up the shutdown of MySQL */
  82. #if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
  83. #define HAVE_CLOSE_SERVER_SOCK 1
  84. #endif
  85. extern "C" { // Because of SCO 3.2V4.2
  86. #include <errno.h>
  87. #include <sys/stat.h>
  88. #ifndef __GNU_LIBRARY__
  89. #define __GNU_LIBRARY__ // Skip warnings in getopt.h
  90. #endif
  91. #include <my_getopt.h>
  92. #ifdef HAVE_SYSENT_H
  93. #include <sysent.h>
  94. #endif
  95. #ifdef HAVE_PWD_H
  96. #include <pwd.h> // For getpwent
  97. #endif
  98. #ifdef HAVE_GRP_H
  99. #include <grp.h>
  100. #endif
  101. #if defined(OS2)
  102. #  include <sys/un.h>
  103. #elif !defined( __WIN__)
  104. #  ifndef __NETWARE__
  105. #include <sys/resource.h>
  106. #  endif /* __NETWARE__ */
  107. #ifdef HAVE_SYS_UN_H
  108. #  include <sys/un.h>
  109. #endif
  110. #include <netdb.h>
  111. #ifdef HAVE_SELECT_H
  112. #  include <select.h>
  113. #endif
  114. #ifdef HAVE_SYS_SELECT_H
  115. #include <sys/select.h>
  116. #endif
  117. #include <sys/utsname.h>
  118. #endif /* __WIN__ */
  119. #ifdef HAVE_LIBWRAP
  120. #include <tcpd.h>
  121. #include <syslog.h>
  122. #ifdef NEED_SYS_SYSLOG_H
  123. #include <sys/syslog.h>
  124. #endif /* NEED_SYS_SYSLOG_H */
  125. int allow_severity = LOG_INFO;
  126. int deny_severity = LOG_WARNING;
  127. #endif /* HAVE_LIBWRAP */
  128. #ifdef HAVE_SYS_MMAN_H
  129. #include <sys/mman.h>
  130. #endif
  131. #define zVOLSTATE_ACTIVE 6
  132. #define zVOLSTATE_DEACTIVE 2
  133. #define zVOLSTATE_MAINTENANCE 3
  134. #ifdef __NETWARE__
  135. #include <nks/netware.h>
  136. #include <nks/vm.h>
  137. #include <library.h>
  138. #include <monitor.h>
  139. #include <zOmni.h>                              //For NEB
  140. #include <neb.h>                                //For NEB
  141. #include <nebpub.h>                             //For NEB
  142. #include <zEvent.h>                             //For NSS event structures
  143. #include <zPublics.h>
  144. static void *neb_consumer_id= NULL;             //For storing NEB consumer id
  145. static char datavolname[256]= {0};
  146. static VolumeID_t datavolid;
  147. static event_handle_t eh;
  148. static Report_t ref;
  149. static void *refneb= NULL;
  150. my_bool event_flag= FALSE;
  151. static int volumeid= -1;
  152.   /* NEB event callback */
  153. unsigned long neb_event_callback(struct EventBlock *eblock);
  154. static void registerwithneb();
  155. static void getvolumename();
  156. static void getvolumeID(BYTE *volumeName);
  157. #endif /* __NETWARE__ */
  158.   
  159. #ifdef _AIX41
  160. int initgroups(const char *,unsigned int);
  161. #endif
  162. #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
  163. #include <ieeefp.h>
  164. #ifdef HAVE_FP_EXCEPT // Fix type conflict
  165. typedef fp_except fp_except_t;
  166. #endif
  167.   /* We can't handle floating point exceptions with threads, so disable
  168.      this on freebsd
  169.   */
  170. inline void reset_floating_point_exceptions()
  171. {
  172.   /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
  173. #if defined(__i386__)
  174.   fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
  175.       FP_X_IMP));
  176. #else
  177.  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
  178.      FP_X_IMP));
  179. #endif
  180. }
  181. #else
  182. #define reset_floating_point_exceptions()
  183. #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
  184. } /* cplusplus */
  185. #if defined(HAVE_LINUXTHREADS)
  186. #define THR_KILL_SIGNAL SIGINT
  187. #else
  188. #define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads
  189. #endif
  190. #define MYSQL_KILL_SIGNAL SIGTERM
  191. #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
  192. #include <sys/types.h>
  193. #else
  194. #include <my_pthread.h> // For thr_setconcurency()
  195. #endif
  196. #ifdef SOLARIS
  197. extern "C" int gethostname(char *name, int namelen);
  198. #endif
  199. /* Constants */
  200. const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
  201. const char *sql_mode_names[] =
  202. {
  203.   "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
  204.   "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
  205.   "NO_DIR_IN_CREATE",
  206.   "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
  207.   "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
  208.   "NO_AUTO_VALUE_ON_ZERO", NullS
  209. };
  210. TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
  211.     sql_mode_names, NULL };
  212. const char *first_keyword= "first", *binary_keyword= "BINARY";
  213. const char *my_localhost= "localhost", *delayed_user= "DELAYED";
  214. #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
  215. #define GET_HA_ROWS GET_ULL
  216. #else
  217. #define GET_HA_ROWS GET_ULONG
  218. #endif
  219. bool opt_large_files= sizeof(my_off_t) > 4;
  220. /*
  221.   Used with --help for detailed option
  222. */
  223. bool opt_help= 0;
  224. bool opt_verbose= 0;
  225. arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
  226. {{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
  227.  {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
  228.  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
  229.  {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row}};
  230. /* Global variables */
  231. bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
  232. bool opt_error_log= IF_WIN(1,0);
  233. bool opt_disable_networking=0, opt_skip_show_db=0;
  234. bool opt_character_set_client_handshake= 1;
  235. bool lower_case_table_names_used= 0;
  236. bool server_id_supplied = 0;
  237. bool opt_endinfo,using_udf_functions, locked_in_memory;
  238. bool opt_using_transactions, using_update_log;
  239. bool volatile abort_loop, select_thread_in_use, signal_thread_in_use;
  240. bool volatile ready_to_exit, shutdown_in_progress, grant_option;
  241. my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted
  242. my_bool opt_reckless_slave = 0;
  243. my_bool opt_enable_named_pipe= 0, opt_debugging= 0;
  244. my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
  245. my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
  246. my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
  247. my_bool opt_log_slave_updates= 0;
  248. my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam, opt_ndbcluster;
  249. #ifdef HAVE_NDBCLUSTER_DB
  250. const char *opt_ndbcluster_connectstring= 0;
  251. my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
  252. #endif
  253. my_bool opt_readonly, use_temp_pool, relay_log_purge;
  254. my_bool opt_sync_bdb_logs, opt_sync_frm, opt_allow_suspicious_udfs;
  255. my_bool opt_secure_auth= 0;
  256. my_bool opt_short_log_format= 0;
  257. my_bool opt_log_queries_not_using_indexes= 0;
  258. my_bool opt_log_slow_admin_statements= 0;
  259. my_bool lower_case_file_system= 0;
  260. my_bool opt_innodb_safe_binlog= 0;
  261. volatile bool mqh_used = 0;
  262. #ifdef HAVE_INITGROUPS
  263. static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
  264. #endif
  265. uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
  266. uint delay_key_write_options, protocol_version;
  267. uint lower_case_table_names;
  268. uint opt_crash_binlog_innodb;
  269. uint volatile thread_count, thread_running, kill_cached_threads, wake_thread;
  270. ulong back_log, connect_timeout, concurrency;
  271. ulong server_id, thd_startup_options;
  272. ulong table_cache_size, thread_stack, thread_stack_min, what_to_log;
  273. ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
  274. ulong open_files_limit, max_binlog_size, max_relay_log_size;
  275. ulong slave_net_timeout, slave_trans_retries;
  276. ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
  277. ulong query_cache_size=0;
  278. ulong com_stat[(uint) SQLCOM_END], com_other;
  279. ulong com_stmt_prepare, com_stmt_execute, com_stmt_send_long_data;
  280. ulong com_stmt_close, com_stmt_reset;
  281. ulong bytes_sent, bytes_received, net_big_packet_count;
  282. ulong refresh_version, flush_version; /* Increments on each reload */
  283. ulong query_id, long_query_count;
  284. ulong aborted_threads, killed_threads, aborted_connects;
  285. ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
  286. ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
  287. ulong delayed_insert_errors,flush_time, thread_created;
  288. ulong filesort_rows, filesort_range_count, filesort_scan_count;
  289. ulong filesort_merge_passes;
  290. ulong select_range_check_count, select_range_count, select_scan_count;
  291. ulong select_full_range_join_count,select_full_join_count;
  292. ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
  293.       created_tmp_disk_tables=0;
  294. ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
  295. ulong max_connections,max_used_connections,
  296.       max_connect_errors, max_user_connections = 0;
  297. ulong thread_id=1L,current_pid;
  298. ulong slow_launch_threads = 0, sync_binlog_period;
  299. ulong expire_logs_days = 0;
  300. ulong rpl_recovery_rank=0;
  301. ulong my_bind_addr; /* the address we bind to */
  302. volatile ulong cached_thread_count= 0;
  303. double log_10[32]; /* 10 potences */
  304. time_t start_time;
  305. char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
  306. char *default_tz_name;
  307. char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
  308. char* log_error_file_ptr= log_error_file;
  309. char mysql_real_data_home[FN_REFLEN],
  310.      language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
  311.      *mysqld_user,*mysqld_chroot, *opt_init_file,
  312.      *opt_init_connect, *opt_init_slave,
  313.      def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
  314. const key_map key_map_empty(0);
  315. key_map key_map_full(0);                        // Will be initialized later
  316. const char *opt_date_time_formats[3];
  317. char *language_ptr, *default_collation_name, *default_character_set_name;
  318. char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
  319. struct passwd *user_info;
  320. char server_version[SERVER_VERSION_LENGTH];
  321. char *mysqld_unix_port, *opt_mysql_tmpdir;
  322. char *my_bind_addr_str;
  323. const char **errmesg; /* Error messages */
  324. const char *myisam_recover_options_str="OFF";
  325. const char *myisam_stats_method_str="nulls_unequal";
  326. const char *sql_mode_str="OFF";
  327. /* name of reference on left espression in rewritten IN subquery */
  328. const char *in_left_expr_name= "<left expr>";
  329. /* name of additional condition */
  330. const char *in_additional_cond= "<IN COND>";
  331. /* classes for comparation parsing/processing */
  332. Eq_creator eq_creator;
  333. Ne_creator ne_creator;
  334. Gt_creator gt_creator;
  335. Lt_creator lt_creator;
  336. Ge_creator ge_creator;
  337. Le_creator le_creator;
  338. FILE *bootstrap_file;
  339. FILE *stderror_file=0;
  340. I_List<i_string_pair> replicate_rewrite_db;
  341. I_List<i_string> replicate_do_db, replicate_ignore_db;
  342. // allow the user to tell us which db to replicate and which to ignore
  343. I_List<i_string> binlog_do_db, binlog_ignore_db;
  344. I_List<THD> threads,thread_cache;
  345. I_List<NAMED_LIST> key_caches;
  346. struct system_variables global_system_variables;
  347. struct system_variables max_system_variables;
  348. MY_TMPDIR mysql_tmpdir_list;
  349. MY_BITMAP temp_pool;
  350. CHARSET_INFO *system_charset_info, *files_charset_info ;
  351. CHARSET_INFO *national_charset_info, *table_alias_charset;
  352. SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster, 
  353.   have_example_db, have_archive_db, have_csv_db;
  354. SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
  355. SHOW_COMP_OPTION have_geometry, have_rtree_keys;
  356. SHOW_COMP_OPTION have_crypt, have_compress;
  357. SHOW_COMP_OPTION have_blackhole_db;
  358. /* Thread specific variables */
  359. pthread_key(MEM_ROOT**,THR_MALLOC);
  360. pthread_key(THD*, THR_THD);
  361. pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
  362. LOCK_mapped_file, LOCK_status,
  363. LOCK_error_log, LOCK_uuid_generator,
  364. LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
  365. LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
  366.         LOCK_global_system_variables,
  367. LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
  368. #ifdef HAVE_OPENSSL
  369. pthread_mutex_t LOCK_des_key_file;
  370. #endif
  371. rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
  372. pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
  373.        COND_slave_start;
  374. pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
  375. pthread_t signal_thread;
  376. pthread_attr_t connection_attrib;
  377. /* replication parameters, if master_host is not NULL, we are a slave */
  378. uint master_port= MYSQL_PORT, master_connect_retry = 60;
  379. uint report_port= MYSQL_PORT;
  380. ulong master_retry_count=0;
  381. char *master_user, *master_password, *master_host, *master_info_file;
  382. char *relay_log_info_file, *report_user, *report_password, *report_host;
  383. char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
  384. my_bool master_ssl;
  385. char *master_ssl_key, *master_ssl_cert;
  386. char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher;
  387. /* Static variables */
  388. static bool kill_in_progress, segfaulted;
  389. static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log;
  390. static int cleanup_done;
  391. static ulong opt_specialflag, opt_myisam_block_size;
  392. static char *opt_logname, *opt_update_logname, *opt_binlog_index_name;
  393. static char *opt_slow_logname;
  394. static char *mysql_home_ptr, *pidfile_name_ptr;
  395. static char **defaults_argv;
  396. static char *opt_bin_logname;
  397. static my_socket unix_sock,ip_sock;
  398. static pthread_t select_thread;
  399. struct rand_struct sql_rand; // used by sql_class.cc:THD::THD()
  400. /* OS specific variables */
  401. #ifdef __WIN__
  402. #undef  getpid
  403. #include <process.h>
  404. static pthread_cond_t COND_handler_count;
  405. static uint handler_count;
  406. static bool start_mode=0, use_opt_args;
  407. static int opt_argc;
  408. static char **opt_argv;
  409. #if !defined(EMBEDDED_LIBRARY)
  410. static HANDLE hEventShutdown;
  411. static char shutdown_event_name[40];
  412. #include "nt_servc.h"
  413. static  NTService  Service;       // Service object for WinNT
  414. #endif /* EMBEDDED_LIBRARY */
  415. #endif /* __WIN__ */
  416. #ifdef __NT__
  417. static char pipe_name[512];
  418. static SECURITY_ATTRIBUTES saPipeSecurity;
  419. static SECURITY_DESCRIPTOR sdPipeDescriptor;
  420. static HANDLE hPipe = INVALID_HANDLE_VALUE;
  421. #endif
  422. #ifdef OS2
  423. pthread_cond_t eventShutdown;
  424. #endif
  425. #ifndef EMBEDDED_LIBRARY
  426. bool mysqld_embedded=0;
  427. #else
  428. bool mysqld_embedded=1;
  429. #endif
  430. #ifndef DBUG_OFF
  431. static const char* default_dbug_option;
  432. #endif
  433. #ifdef HAVE_LIBWRAP
  434. char *libwrapName= NULL;
  435. #endif
  436. #ifdef HAVE_QUERY_CACHE
  437. ulong query_cache_limit= 0;
  438. ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
  439. Query_cache query_cache;
  440. #endif
  441. #ifdef HAVE_SMEM
  442. char *shared_memory_base_name= default_shared_memory_base_name;
  443. bool opt_enable_shared_memory;
  444. HANDLE smem_event_connect_request= 0;
  445. #endif
  446. #include "sslopt-vars.h"
  447. #ifdef HAVE_OPENSSL
  448. #include <openssl/crypto.h>
  449. typedef struct CRYPTO_dynlock_value
  450. {
  451.   rw_lock_t lock;
  452. } openssl_lock_t;
  453. char *des_key_file;
  454. struct st_VioSSLAcceptorFd *ssl_acceptor_fd;
  455. static openssl_lock_t *openssl_stdlocks;
  456. static openssl_lock_t *openssl_dynlock_create(const char *, int);
  457. static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
  458. static void openssl_lock_function(int, int, const char *, int);
  459. static void openssl_lock(int, openssl_lock_t *, const char *, int);
  460. static unsigned long openssl_id_function();
  461. #endif /* HAVE_OPENSSL */
  462. /* Function declarations */
  463. static void start_signal_handler(void);
  464. extern "C" pthread_handler_decl(signal_hand, arg);
  465. static void mysql_init_variables(void);
  466. static void get_options(int argc,char **argv);
  467. static void set_server_version(void);
  468. static int init_thread_environment();
  469. static char *get_relative_path(const char *path);
  470. static void fix_paths(void);
  471. extern "C" pthread_handler_decl(handle_connections_sockets,arg);
  472. extern "C" pthread_handler_decl(kill_server_thread,arg);
  473. static int bootstrap(FILE *file);
  474. static void close_server_sock();
  475. static bool read_init_file(char *file_name);
  476. #ifdef __NT__
  477. extern "C" pthread_handler_decl(handle_connections_namedpipes,arg);
  478. #endif
  479. #ifdef HAVE_SMEM
  480. static pthread_handler_decl(handle_connections_shared_memory,arg);
  481. #endif
  482. extern "C" pthread_handler_decl(handle_slave,arg);
  483. static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
  484. static void clean_up(bool print_message);
  485. static void clean_up_mutexes(void);
  486. static void wait_for_signal_thread_to_end(void);
  487. static int test_if_case_insensitive(const char *dir_name);
  488. static void create_pid_file();
  489. #ifndef EMBEDDED_LIBRARY
  490. /****************************************************************************
  491. ** Code to end mysqld
  492. ****************************************************************************/
  493. static void close_connections(void)
  494. {
  495. #ifdef EXTRA_DEBUG
  496.   int count=0;
  497. #endif
  498.   DBUG_ENTER("close_connections");
  499.   /* Clear thread cache */
  500.   kill_cached_threads++;
  501.   flush_thread_cache();
  502.   /* kill flush thread */
  503.   (void) pthread_mutex_lock(&LOCK_manager);
  504.   if (manager_thread_in_use)
  505.   {
  506.     DBUG_PRINT("quit",("killing manager thread: %lx",manager_thread));
  507.    (void) pthread_cond_signal(&COND_manager);
  508.   }
  509.   (void) pthread_mutex_unlock(&LOCK_manager);
  510.   /* kill connection thread */
  511. #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
  512.   DBUG_PRINT("quit",("waiting for select thread: %lx",select_thread));
  513.   (void) pthread_mutex_lock(&LOCK_thread_count);
  514.   while (select_thread_in_use)
  515.   {
  516.     struct timespec abstime;
  517.     int error;
  518.     LINT_INIT(error);
  519.     DBUG_PRINT("info",("Waiting for select thread"));
  520. #ifndef DONT_USE_THR_ALARM
  521.     if (pthread_kill(select_thread,THR_CLIENT_ALARM))
  522.       break; // allready dead
  523. #endif
  524.     set_timespec(abstime, 2);
  525.     for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
  526.     {
  527.       error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
  528.    &abstime);
  529.       if (error != EINTR)
  530. break;
  531.     }
  532. #ifdef EXTRA_DEBUG
  533.     if (error != 0 && !count++)
  534.       sql_print_error("Got error %d from pthread_cond_timedwait",error);
  535. #endif
  536.     close_server_sock();
  537.   }
  538.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  539. #endif /* __WIN__ */
  540.   /* Abort listening to new connections */
  541.   DBUG_PRINT("quit",("Closing sockets"));
  542.   if ( !opt_disable_networking )
  543.   {
  544.     if (ip_sock != INVALID_SOCKET)
  545.     {
  546.       (void) shutdown(ip_sock,2);
  547.       (void) closesocket(ip_sock);
  548.       ip_sock= INVALID_SOCKET;
  549.     }
  550.   }
  551. #ifdef __NT__
  552.   if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
  553.   {
  554.     HANDLE temp;
  555.     DBUG_PRINT( "quit", ("Closing named pipes") );
  556.     /* Create connection to the handle named pipe handler to break the loop */
  557.     if ((temp = CreateFile(pipe_name,
  558.    GENERIC_READ | GENERIC_WRITE,
  559.    0,
  560.    NULL,
  561.    OPEN_EXISTING,
  562.    0,
  563.    NULL )) != INVALID_HANDLE_VALUE)
  564.     {
  565.       WaitNamedPipe(pipe_name, 1000);
  566.       DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
  567.       SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
  568.       CancelIo(temp);
  569.       DisconnectNamedPipe(temp);
  570.       CloseHandle(temp);
  571.     }
  572.   }
  573. #endif
  574. #ifdef HAVE_SYS_UN_H
  575.   if (unix_sock != INVALID_SOCKET)
  576.   {
  577.     (void) shutdown(unix_sock,2);
  578.     (void) closesocket(unix_sock);
  579.     (void) unlink(mysqld_unix_port);
  580.     unix_sock= INVALID_SOCKET;
  581.   }
  582. #endif
  583.   end_thr_alarm(0);  // Abort old alarms.
  584.   /*
  585.     First signal all threads that it's time to die
  586.     This will give the threads some time to gracefully abort their
  587.     statements and inform their clients that the server is about to die.
  588.   */
  589.   THD *tmp;
  590.   (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
  591.   I_List_iterator<THD> it(threads);
  592.   while ((tmp=it++))
  593.   {
  594.     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
  595.        tmp->thread_id));
  596.     /* We skip slave threads on this first loop through. */
  597.     if (tmp->slave_thread) continue;
  598.     tmp->killed= 1;
  599.     if (tmp->mysys_var)
  600.     {
  601.       tmp->mysys_var->abort=1;
  602.       pthread_mutex_lock(&tmp->mysys_var->mutex);
  603.       if (tmp->mysys_var->current_cond)
  604.       {
  605. pthread_mutex_lock(tmp->mysys_var->current_mutex);
  606. pthread_cond_broadcast(tmp->mysys_var->current_cond);
  607. pthread_mutex_unlock(tmp->mysys_var->current_mutex);
  608.       }
  609.       pthread_mutex_unlock(&tmp->mysys_var->mutex);
  610.     }
  611.   }
  612.   (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
  613.   end_slave();
  614.   if (thread_count)
  615.     sleep(2); // Give threads time to die
  616.   /*
  617.     Force remaining threads to die by closing the connection to the client
  618.     This will ensure that threads that are waiting for a command from the
  619.     client on a blocking read call are aborted.
  620.   */
  621.   for (;;)
  622.   {
  623.     DBUG_PRINT("quit",("Locking LOCK_thread_count"));
  624.     (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
  625.     if (!(tmp=threads.get()))
  626.     {
  627.       DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
  628.       (void) pthread_mutex_unlock(&LOCK_thread_count);
  629.       break;
  630.     }
  631. #ifndef __bsdi__ // Bug in BSDI kernel
  632.     if (tmp->vio_ok())
  633.     {
  634.       if (global_system_variables.log_warnings)
  635.         sql_print_warning(ER(ER_FORCING_CLOSE),my_progname,
  636.                           tmp->thread_id,tmp->user ? tmp->user : "");
  637.       close_connection(tmp,0,0);
  638.     }
  639. #endif
  640.     DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
  641.     (void) pthread_mutex_unlock(&LOCK_thread_count);
  642.   }
  643.   /* All threads has now been aborted */
  644.   DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
  645.   (void) pthread_mutex_lock(&LOCK_thread_count);
  646.   while (thread_count)
  647.   {
  648.     (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
  649.     DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  650.   }
  651.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  652.   DBUG_PRINT("quit",("close_connections thread"));
  653.   DBUG_VOID_RETURN;
  654. }
  655. #endif /*EMBEDDED_LIBRARY*/
  656. static void close_server_sock()
  657. {
  658. #ifdef HAVE_CLOSE_SERVER_SOCK
  659.   DBUG_ENTER("close_server_sock");
  660.   my_socket tmp_sock;
  661.   tmp_sock=ip_sock;
  662.   if (tmp_sock != INVALID_SOCKET)
  663.   {
  664.     ip_sock=INVALID_SOCKET;
  665.     DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
  666.     VOID(shutdown(tmp_sock,2));
  667. #if defined(__NETWARE__)
  668.     /*
  669.       The following code is disabled for normal systems as it causes MySQL
  670.       to hang on AIX 4.3 during shutdown
  671.     */
  672.     DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
  673.     VOID(closesocket(tmp_sock));
  674. #endif
  675.   }
  676.   tmp_sock=unix_sock;
  677.   if (tmp_sock != INVALID_SOCKET)
  678.   {
  679.     unix_sock=INVALID_SOCKET;
  680.     DBUG_PRINT("info",("calling shutdown on unix socket"));
  681.     VOID(shutdown(tmp_sock,2));
  682. #if defined(__NETWARE__)
  683.     /*
  684.       The following code is disabled for normal systems as it may cause MySQL
  685.       to hang on AIX 4.3 during shutdown
  686.     */
  687.     DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
  688.     VOID(closesocket(tmp_sock));
  689. #endif
  690.     VOID(unlink(mysqld_unix_port));
  691.   }
  692.   DBUG_VOID_RETURN;
  693. #endif
  694. }
  695. void kill_mysql(void)
  696. {
  697.   DBUG_ENTER("kill_mysql");
  698. #ifdef SIGNALS_DONT_BREAK_READ
  699.   abort_loop=1; // Break connection loops
  700.   close_server_sock(); // Force accept to wake up
  701. #endif
  702. #if defined(__WIN__)
  703. #if !defined(EMBEDDED_LIBRARY)
  704.   {
  705.     if (!SetEvent(hEventShutdown))
  706.     {
  707.       DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
  708.     }
  709.     /*
  710.       or:
  711.       HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
  712.       SetEvent(hEventShutdown);
  713.       CloseHandle(hEvent);
  714.     */
  715.   }
  716. #endif
  717. #elif defined(OS2)
  718.   pthread_cond_signal( &eventShutdown); // post semaphore
  719. #elif defined(HAVE_PTHREAD_KILL)
  720.   if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
  721.   {
  722.     DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
  723.   }
  724. #elif !defined(SIGNALS_DONT_BREAK_READ)
  725.   kill(current_pid, MYSQL_KILL_SIGNAL);
  726. #endif
  727.   DBUG_PRINT("quit",("After pthread_kill"));
  728.   shutdown_in_progress=1; // Safety if kill didn't work
  729. #ifdef SIGNALS_DONT_BREAK_READ
  730.   if (!kill_in_progress)
  731.   {
  732.     pthread_t tmp;
  733.     abort_loop=1;
  734.     if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
  735.    (void*) 0))
  736.       sql_print_error("Can't create thread to kill server");
  737.   }
  738. #endif
  739.   DBUG_VOID_RETURN;
  740. }
  741. /* Force server down. kill all connections and threads and exit */
  742. #if defined(OS2) || defined(__NETWARE__)
  743. extern "C" void kill_server(int sig_ptr)
  744. #define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
  745. #elif !defined(__WIN__)
  746. static void *kill_server(void *sig_ptr)
  747. #define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
  748. #else
  749. static void __cdecl kill_server(int sig_ptr)
  750. #define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
  751. #endif
  752. {
  753.   int sig=(int) (long) sig_ptr; // This is passed a int
  754.   DBUG_ENTER("kill_server");
  755. #ifndef EMBEDDED_LIBRARY
  756.   // if there is a signal during the kill in progress, ignore the other
  757.   if (kill_in_progress) // Safety
  758.     RETURN_FROM_KILL_SERVER;
  759.   kill_in_progress=TRUE;
  760.   abort_loop=1; // This should be set
  761.   my_sigset(sig,SIG_IGN);
  762.   if (sig == MYSQL_KILL_SIGNAL || sig == 0)
  763.     sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname);
  764.   else
  765.     sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
  766. #if defined(HAVE_SMEM) && defined(__WIN__)    
  767.   /*    
  768.    Send event to smem_event_connect_request for aborting    
  769.    */    
  770.   if (!SetEvent(smem_event_connect_request))    
  771.   {      
  772.   DBUG_PRINT("error",
  773. ("Got error: %ld from SetEvent of smem_event_connect_request",
  774.  GetLastError()));    
  775.   }
  776. #endif  
  777.   
  778. #if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
  779.   my_thread_init(); // If this is a new thread
  780. #endif
  781.   close_connections();
  782.   if (sig != MYSQL_KILL_SIGNAL && sig != 0)
  783.     unireg_abort(1); /* purecov: inspected */
  784.   else
  785.     unireg_end();
  786. #ifdef __NETWARE__
  787.   if (!event_flag)
  788.       pthread_join(select_thread, NULL); // wait for main thread
  789. #endif /* __NETWARE__ */
  790.   pthread_exit(0); /* purecov: deadcode */
  791. #endif /* EMBEDDED_LIBRARY */
  792.   RETURN_FROM_KILL_SERVER;
  793. }
  794. #if defined(USE_ONE_SIGNAL_HAND) || (defined(__NETWARE__) && defined(SIGNALS_DONT_BREAK_READ))
  795. extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
  796. {
  797.   my_thread_init(); // Initialize new thread
  798.   kill_server(0);
  799.   my_thread_end(); // Normally never reached
  800.   return 0;
  801. }
  802. #endif
  803. extern "C" sig_handler print_signal_warning(int sig)
  804. {
  805.   if (!DBUG_IN_USE)
  806.   {
  807.     if (global_system_variables.log_warnings)
  808.       sql_print_warning("Got signal %d from thread %d",
  809.       sig,my_thread_id());
  810.   }
  811. #ifdef DONT_REMEMBER_SIGNAL
  812.   my_sigset(sig,print_signal_warning); /* int. thread system calls */
  813. #endif
  814. #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
  815.   if (sig == SIGALRM)
  816.     alarm(2); /* reschedule alarm */
  817. #endif
  818. }
  819. /*
  820.   cleanup all memory and end program nicely
  821.   SYNOPSIS
  822.     unireg_end()
  823.   NOTES
  824.     This function never returns.
  825.     If SIGNALS_DONT_BREAK_READ is defined, this function is called
  826.     by the main thread. To get MySQL to shut down nicely in this case
  827.     (Mac OS X) we have to call exit() instead if pthread_exit().
  828. */
  829. #ifndef EMBEDDED_LIBRARY
  830. void unireg_end(void)
  831. {
  832.   clean_up(1);
  833.   my_thread_end();
  834. #if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
  835.   exit(0);
  836. #else
  837.   pthread_exit(0); // Exit is in main thread
  838. #endif
  839. }
  840. extern "C" void unireg_abort(int exit_code)
  841. {
  842.   DBUG_ENTER("unireg_abort");
  843.   if (exit_code)
  844.     sql_print_error("Abortingn");
  845.   clean_up(exit_code || !opt_bootstrap); /* purecov: inspected */
  846.   DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
  847.   wait_for_signal_thread_to_end();
  848.   clean_up_mutexes();
  849.   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
  850.   exit(exit_code); /* purecov: inspected */
  851. }
  852. #endif
  853. void clean_up(bool print_message)
  854. {
  855.   DBUG_PRINT("exit",("clean_up"));
  856.   if (cleanup_done++)
  857.     return; /* purecov: inspected */
  858.   mysql_log.cleanup();
  859.   mysql_slow_log.cleanup();
  860.   mysql_update_log.cleanup();
  861.   mysql_bin_log.cleanup();
  862. #ifdef HAVE_REPLICATION
  863.   if (use_slave_mask)
  864.     bitmap_free(&slave_error_mask);
  865. #endif
  866.   my_tz_free();
  867.   my_dbopt_free();
  868. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  869.   acl_free(1);
  870.   grant_free();
  871. #endif
  872.   query_cache_destroy();
  873.   table_cache_free();
  874.   hostname_cache_free();
  875.   item_user_lock_free();
  876.   lex_free(); /* Free some memory */
  877.   set_var_free();
  878.   free_charsets();
  879. #ifdef HAVE_DLOPEN
  880.   if (!opt_noacl)
  881.     udf_free();
  882. #endif
  883.   (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
  884.   delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
  885.   multi_keycache_free();
  886.   end_thr_alarm(1); /* Free allocated memory */
  887. #ifdef USE_RAID
  888.   end_raid();
  889. #endif
  890.   my_free_open_file_info();
  891.   my_free((char*) global_system_variables.date_format,
  892.   MYF(MY_ALLOW_ZERO_PTR));
  893.   my_free((char*) global_system_variables.time_format,
  894.   MYF(MY_ALLOW_ZERO_PTR));
  895.   my_free((char*) global_system_variables.datetime_format,
  896.   MYF(MY_ALLOW_ZERO_PTR));
  897.   if (defaults_argv)
  898.     free_defaults(defaults_argv);
  899.   my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
  900.   my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
  901.   free_tmpdir(&mysql_tmpdir_list);
  902. #ifdef HAVE_REPLICATION
  903.   my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
  904. #endif
  905.   x_free(opt_bin_logname);
  906.   x_free(opt_relay_logname);
  907.   bitmap_free(&temp_pool);
  908.   free_max_user_conn();
  909. #ifdef HAVE_REPLICATION
  910.   end_slave_list();
  911.   free_list(&replicate_do_db);
  912.   free_list(&replicate_ignore_db);
  913.   free_list(&binlog_do_db);
  914.   free_list(&binlog_ignore_db);
  915.   free_list(&replicate_rewrite_db);
  916. #endif
  917. #ifdef HAVE_OPENSSL
  918.   if (ssl_acceptor_fd)
  919.     my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
  920. #endif /* HAVE_OPENSSL */
  921. #ifdef USE_REGEX
  922.   my_regex_end();
  923. #endif
  924.   if (print_message && errmesg)
  925.     sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
  926. #if !defined(EMBEDDED_LIBRARY)
  927.   if (!opt_bootstrap)
  928.     (void) my_delete(pidfile_name,MYF(0)); // This may not always exist
  929. #endif
  930.   x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
  931.   DBUG_PRINT("quit", ("Error messages freed"));
  932.   /* Tell main we are ready */
  933.   (void) pthread_mutex_lock(&LOCK_thread_count);
  934.   DBUG_PRINT("quit", ("got thread count lock"));
  935.   ready_to_exit=1;
  936.   /* do the broadcast inside the lock to ensure that my_end() is not called */
  937.   (void) pthread_cond_broadcast(&COND_thread_count);
  938.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  939.   /*
  940.     The following lines may never be executed as the main thread may have
  941.     killed us
  942.   */
  943.   DBUG_PRINT("quit", ("done with cleanup"));
  944. } /* clean_up */
  945. /*
  946.   This is mainly needed when running with purify, but it's still nice to
  947.   know that all child threads have died when mysqld exits
  948. */
  949. static void wait_for_signal_thread_to_end()
  950. {
  951. #ifndef __NETWARE__
  952.   uint i;
  953.   /*
  954.     Wait up to 10 seconds for signal thread to die. We use this mainly to
  955.     avoid getting warnings that my_thread_end has not been called
  956.   */
  957.   for (i= 0 ; i < 100 && signal_thread_in_use; i++)
  958.   {
  959.     if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
  960.       break;
  961.     my_sleep(100); // Give it time to die
  962.   }
  963. #endif
  964. }
  965. static void clean_up_mutexes()
  966. {
  967.   (void) pthread_mutex_destroy(&LOCK_mysql_create_db);
  968.   (void) pthread_mutex_destroy(&LOCK_Acl);
  969.   (void) rwlock_destroy(&LOCK_grant);
  970.   (void) pthread_mutex_destroy(&LOCK_open);
  971.   (void) pthread_mutex_destroy(&LOCK_thread_count);
  972.   (void) pthread_mutex_destroy(&LOCK_mapped_file);
  973.   (void) pthread_mutex_destroy(&LOCK_status);
  974.   (void) pthread_mutex_destroy(&LOCK_error_log);
  975.   (void) pthread_mutex_destroy(&LOCK_delayed_insert);
  976.   (void) pthread_mutex_destroy(&LOCK_delayed_status);
  977.   (void) pthread_mutex_destroy(&LOCK_delayed_create);
  978.   (void) pthread_mutex_destroy(&LOCK_manager);
  979.   (void) pthread_mutex_destroy(&LOCK_crypt);
  980.   (void) pthread_mutex_destroy(&LOCK_bytes_sent);
  981.   (void) pthread_mutex_destroy(&LOCK_bytes_received);
  982.   (void) pthread_mutex_destroy(&LOCK_user_conn);
  983. #ifdef HAVE_OPENSSL
  984.   (void) pthread_mutex_destroy(&LOCK_des_key_file);
  985.   for (int i= 0; i < CRYPTO_num_locks(); ++i)
  986.     (void) rwlock_destroy(&openssl_stdlocks[i].lock);
  987.   OPENSSL_free(openssl_stdlocks);
  988. #endif
  989. #ifdef HAVE_REPLICATION
  990.   (void) pthread_mutex_destroy(&LOCK_rpl_status);
  991.   (void) pthread_cond_destroy(&COND_rpl_status);
  992. #endif
  993.   (void) pthread_mutex_destroy(&LOCK_active_mi);
  994.   (void) rwlock_destroy(&LOCK_sys_init_connect);
  995.   (void) rwlock_destroy(&LOCK_sys_init_slave);
  996.   (void) pthread_mutex_destroy(&LOCK_global_system_variables);
  997.   (void) pthread_cond_destroy(&COND_thread_count);
  998.   (void) pthread_cond_destroy(&COND_refresh);
  999.   (void) pthread_cond_destroy(&COND_thread_cache);
  1000.   (void) pthread_cond_destroy(&COND_flush_thread_cache);
  1001.   (void) pthread_cond_destroy(&COND_manager);
  1002. }
  1003. /****************************************************************************
  1004. ** Init IP and UNIX socket
  1005. ****************************************************************************/
  1006. static void set_ports()
  1007. {
  1008.   char *env;
  1009.   if (!mysqld_port && !opt_disable_networking)
  1010.   { // Get port if not from commandline
  1011.     struct  servent *serv_ptr;
  1012.     mysqld_port= MYSQL_PORT;
  1013.     if ((serv_ptr= getservbyname("mysql", "tcp")))
  1014.       mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
  1015.     if ((env = getenv("MYSQL_TCP_PORT")))
  1016.       mysqld_port= (uint) atoi(env); /* purecov: inspected */
  1017.   }
  1018.   if (!mysqld_unix_port)
  1019.   {
  1020. #ifdef __WIN__
  1021.     mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
  1022. #else
  1023.     mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
  1024. #endif
  1025.     if ((env = getenv("MYSQL_UNIX_PORT")))
  1026.       mysqld_unix_port= env; /* purecov: inspected */
  1027.   }
  1028. }
  1029. #ifndef EMBEDDED_LIBRARY
  1030. /* Change to run as another user if started with --user */
  1031. static struct passwd *check_user(const char *user)
  1032. {
  1033. #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
  1034.   struct passwd *user_info;
  1035.   uid_t user_id= geteuid();
  1036.   // Don't bother if we aren't superuser
  1037.   if (user_id)
  1038.   {
  1039.     if (user)
  1040.     {
  1041.       // Don't give a warning, if real user is same as given with --user
  1042.       user_info= getpwnam(user);
  1043.       if ((!user_info || user_id != user_info->pw_uid) &&
  1044.   global_system_variables.log_warnings)
  1045.         sql_print_warning(
  1046.                     "One can only use the --user switch if running as rootn");
  1047.     }
  1048.     return NULL;
  1049.   }
  1050.   if (!user)
  1051.   {
  1052.     if (!opt_bootstrap)
  1053.     {
  1054.       sql_print_error("Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root!n");
  1055.       unireg_abort(1);
  1056.     }
  1057.     return NULL;
  1058.   }
  1059.   if (!strcmp(user,"root"))
  1060.     return NULL;                        // Avoid problem with dynamic libraries
  1061.   if (!(user_info= getpwnam(user)))
  1062.   {
  1063.     // Allow a numeric uid to be used
  1064.     const char *pos;
  1065.     for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
  1066.     if (*pos)                                   // Not numeric id
  1067.       goto err;
  1068.     if (!(user_info= getpwuid(atoi(user))))
  1069.       goto err;
  1070.     else
  1071.       return user_info;
  1072.   }
  1073.   else
  1074.     return user_info;
  1075. err:
  1076.   sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!n",user);
  1077.   unireg_abort(1);
  1078. #endif
  1079.   return NULL;
  1080. }
  1081. static void set_user(const char *user, struct passwd *user_info)
  1082. {
  1083. #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
  1084.   DBUG_ASSERT(user_info);
  1085. #ifdef HAVE_INITGROUPS
  1086.   /*
  1087.     We can get a SIGSEGV when calling initgroups() on some systems when NSS
  1088.     is configured to use LDAP and the server is statically linked.  We set
  1089.     calling_initgroups as a flag to the SIGSEGV handler that is then used to
  1090.     output a specific message to help the user resolve this problem.
  1091.   */
  1092.   calling_initgroups= TRUE;
  1093.   initgroups((char*) user, user_info->pw_gid);
  1094.   calling_initgroups= FALSE;
  1095. #endif
  1096.   if (setgid(user_info->pw_gid) == -1)
  1097.   {
  1098.     sql_perror("setgid");
  1099.     unireg_abort(1);
  1100.   }
  1101.   if (setuid(user_info->pw_uid) == -1)
  1102.   {
  1103.     sql_perror("setuid");
  1104.     unireg_abort(1);
  1105.   }
  1106. #endif
  1107. }
  1108. static void set_effective_user(struct passwd *user_info)
  1109. {
  1110. #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
  1111.   DBUG_ASSERT(user_info);
  1112.   if (setregid((gid_t)-1, user_info->pw_gid) == -1)
  1113.   {
  1114.     sql_perror("setregid");
  1115.     unireg_abort(1);
  1116.   }
  1117.   if (setreuid((uid_t)-1, user_info->pw_uid) == -1)
  1118.   {
  1119.     sql_perror("setreuid");
  1120.     unireg_abort(1);
  1121.   }
  1122. #endif
  1123. }
  1124. /* Change root user if started with  --chroot */
  1125. static void set_root(const char *path)
  1126. {
  1127. #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
  1128.   if (chroot(path) == -1)
  1129.   {
  1130.     sql_perror("chroot");
  1131.     unireg_abort(1);
  1132.   }
  1133.   my_setwd("/", MYF(0));
  1134. #endif
  1135. }
  1136. static void server_init(void)
  1137. {
  1138.   struct sockaddr_in IPaddr;
  1139. #ifdef HAVE_SYS_UN_H
  1140.   struct sockaddr_un UNIXaddr;
  1141. #endif
  1142.   int arg=1;
  1143.   DBUG_ENTER("server_init");
  1144. #ifdef __WIN__
  1145.   if ( !opt_disable_networking )
  1146.   {
  1147.     WSADATA WsaData;
  1148.     if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
  1149.     {
  1150.       my_message(0,"WSAStartup Failedn",MYF(0));
  1151.       unireg_abort(1);
  1152.     }
  1153.   }
  1154. #endif /* __WIN__ */
  1155.   set_ports();
  1156.   if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
  1157.   {
  1158.     DBUG_PRINT("general",("IP Socket is %d",mysqld_port));
  1159.     ip_sock = socket(AF_INET, SOCK_STREAM, 0);
  1160.     if (ip_sock == INVALID_SOCKET)
  1161.     {
  1162.       DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
  1163.       sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */
  1164.       unireg_abort(1); /* purecov: tested */
  1165.     }
  1166.     bzero((char*) &IPaddr, sizeof(IPaddr));
  1167.     IPaddr.sin_family = AF_INET;
  1168.     IPaddr.sin_addr.s_addr = my_bind_addr;
  1169.     IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port);
  1170. #ifndef __WIN__
  1171.     /*
  1172.       We should not use SO_REUSEADDR on windows as this would enable a
  1173.       user to open two mysqld servers with the same TCP/IP port.
  1174.     */
  1175.     (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
  1176. #endif /* __WIN__ */
  1177.     if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr),
  1178.      sizeof(IPaddr)) < 0)
  1179.     {
  1180.       DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
  1181.       sql_perror("Can't start server: Bind on TCP/IP port");
  1182.       sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
  1183.       unireg_abort(1);
  1184.     }
  1185.     if (listen(ip_sock,(int) back_log) < 0)
  1186.     {
  1187.       sql_perror("Can't start server: listen() on TCP/IP port");
  1188.       sql_print_error("listen() on TCP/IP failed with error %d",
  1189.       socket_errno);
  1190.       unireg_abort(1);
  1191.     }
  1192.   }
  1193.   if ((user_info= check_user(mysqld_user)))
  1194.   {
  1195. #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
  1196.     if (locked_in_memory) // getuid() == 0 here
  1197.       set_effective_user(user_info);
  1198.     else
  1199. #endif
  1200.       set_user(mysqld_user, user_info);
  1201.   }
  1202. #ifdef __NT__
  1203.   /* create named pipe */
  1204.   if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
  1205.       opt_enable_named_pipe)
  1206.   {
  1207.     
  1208.     pipe_name[sizeof(pipe_name)-1]= 0; /* Safety if too long string */
  1209.     strxnmov(pipe_name, sizeof(pipe_name)-1, "\\.\pipe\",
  1210.      mysqld_unix_port, NullS);
  1211.     bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
  1212.     bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
  1213.     if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
  1214.       SECURITY_DESCRIPTOR_REVISION))
  1215.     {
  1216.       sql_perror("Can't start server : Initialize security descriptor");
  1217.       unireg_abort(1);
  1218.     }
  1219.     if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
  1220.     {
  1221.       sql_perror("Can't start server : Set security descriptor");
  1222.       unireg_abort(1);
  1223.     }
  1224.     saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES );
  1225.     saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
  1226.     saPipeSecurity.bInheritHandle = FALSE;
  1227.     if ((hPipe= CreateNamedPipe(pipe_name,
  1228. PIPE_ACCESS_DUPLEX,
  1229. PIPE_TYPE_BYTE |
  1230. PIPE_READMODE_BYTE |
  1231. PIPE_WAIT,
  1232. PIPE_UNLIMITED_INSTANCES,
  1233. (int) global_system_variables.net_buffer_length,
  1234. (int) global_system_variables.net_buffer_length,
  1235. NMPWAIT_USE_DEFAULT_WAIT,
  1236. &saPipeSecurity)) == INVALID_HANDLE_VALUE)
  1237.       {
  1238. LPVOID lpMsgBuf;
  1239. int error=GetLastError();
  1240. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1241.       FORMAT_MESSAGE_FROM_SYSTEM,
  1242.       NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1243.       (LPTSTR) &lpMsgBuf, 0, NULL );
  1244. MessageBox( NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
  1245.     MB_OK|MB_ICONINFORMATION );
  1246. LocalFree( lpMsgBuf );
  1247. unireg_abort(1);
  1248.       }
  1249.   }
  1250. #endif
  1251. #if defined(HAVE_SYS_UN_H)
  1252.   /*
  1253.   ** Create the UNIX socket
  1254.   */
  1255.   if (mysqld_unix_port[0] && !opt_bootstrap)
  1256.   {
  1257.     DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
  1258.     if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
  1259.     {
  1260.       sql_print_error("The socket file path is too long (> %d): %s",
  1261.                     sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
  1262.       unireg_abort(1);
  1263.     }
  1264.     if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  1265.     {
  1266.       sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
  1267.       unireg_abort(1); /* purecov: inspected */
  1268.     }
  1269.     bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
  1270.     UNIXaddr.sun_family = AF_UNIX;
  1271.     strmov(UNIXaddr.sun_path, mysqld_unix_port);
  1272.     (void) unlink(mysqld_unix_port);
  1273.     (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
  1274.       sizeof(arg));
  1275.     umask(0);
  1276.     if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
  1277.      sizeof(UNIXaddr)) < 0)
  1278.     {
  1279.       sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
  1280.       sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
  1281.       unireg_abort(1); /* purecov: tested */
  1282.     }
  1283.     umask(((~my_umask) & 0666));
  1284. #if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
  1285.     (void) chmod(mysqld_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */
  1286. #endif
  1287.     if (listen(unix_sock,(int) back_log) < 0)
  1288.       sql_print_warning("listen() on Unix socket failed with error %d",
  1289.       socket_errno);
  1290.   }
  1291. #endif
  1292.   DBUG_PRINT("info",("server started"));
  1293.   DBUG_VOID_RETURN;
  1294. }
  1295. #endif /*!EMBEDDED_LIBRARY*/
  1296. void yyerror(const char *s)
  1297. {
  1298.   THD *thd=current_thd;
  1299.   char *yytext= (char*) thd->lex->tok_start;
  1300.   /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
  1301.   if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
  1302.     s=ER(ER_SYNTAX_ERROR);
  1303.   net_printf(thd,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
  1304.      thd->lex->yylineno);
  1305. }
  1306. #ifndef EMBEDDED_LIBRARY
  1307. /*
  1308.   Close a connection
  1309.   SYNOPSIS
  1310.     close_connection()
  1311.     thd Thread handle
  1312.     errcode Error code to print to console
  1313.     lock 1 if we have have to lock LOCK_thread_count
  1314.   NOTES
  1315.     For the connection that is doing shutdown, this is called twice
  1316. */
  1317. void close_connection(THD *thd, uint errcode, bool lock)
  1318. {
  1319.   st_vio *vio;
  1320.   DBUG_ENTER("close_connection");
  1321.   DBUG_PRINT("enter",("fd: %s  error: '%s'",
  1322.       thd->net.vio ? vio_description(thd->net.vio) :
  1323.       "(not connected)",
  1324.       errcode ? ER(errcode) : ""));
  1325.   if (lock)
  1326.     (void) pthread_mutex_lock(&LOCK_thread_count);
  1327.   thd->killed=1;
  1328.   if ((vio=thd->net.vio) != 0)
  1329.   {
  1330.     if (errcode)
  1331.       send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
  1332.     vio_close(vio); /* vio is freed in delete thd */
  1333.   }
  1334.   if (lock)
  1335.     (void) pthread_mutex_unlock(&LOCK_thread_count);
  1336.   DBUG_VOID_RETURN;
  1337. }
  1338. #endif /* EMBEDDED_LIBRARY */
  1339. /* Called when a thread is aborted */
  1340. /* ARGSUSED */
  1341. extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
  1342. {
  1343.   THD *thd=current_thd;
  1344.   DBUG_ENTER("end_thread_signal");
  1345.   if (thd && ! thd->bootstrap)
  1346.   {
  1347.     statistic_increment(killed_threads, &LOCK_status);
  1348.     end_thread(thd,0);
  1349.   }
  1350.   DBUG_VOID_RETURN; /* purecov: deadcode */
  1351. }
  1352. void end_thread(THD *thd, bool put_in_cache)
  1353. {
  1354.   DBUG_ENTER("end_thread");
  1355.   thd->cleanup();
  1356.   (void) pthread_mutex_lock(&LOCK_thread_count);
  1357.   thread_count--;
  1358.   delete thd;
  1359.   if (put_in_cache && cached_thread_count < thread_cache_size &&
  1360.       ! abort_loop && !kill_cached_threads)
  1361.   {
  1362.     /* Don't kill the thread, just put it in cache for reuse */
  1363.     DBUG_PRINT("info", ("Adding thread to cache"))
  1364.     cached_thread_count++;
  1365.     while (!abort_loop && ! wake_thread && ! kill_cached_threads)
  1366.       (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
  1367.     cached_thread_count--;
  1368.     if (kill_cached_threads)
  1369.       pthread_cond_signal(&COND_flush_thread_cache);
  1370.     if (wake_thread)
  1371.     {
  1372.       wake_thread--;
  1373.       thd=thread_cache.get();
  1374.       thd->real_id=pthread_self();
  1375.       (void) thd->store_globals();
  1376.       thd->thr_create_time= time(NULL);
  1377.       threads.append(thd);
  1378.       pthread_mutex_unlock(&LOCK_thread_count);
  1379.       DBUG_VOID_RETURN;
  1380.     }
  1381.   }
  1382.   DBUG_PRINT("info", ("sending a broadcast"))
  1383.   /* Tell main we are ready */
  1384.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  1385.   /* It's safe to broadcast outside a lock (COND... is not deleted here) */
  1386.   (void) pthread_cond_broadcast(&COND_thread_count);
  1387.   DBUG_PRINT("info", ("unlocked thread_count mutex"))
  1388. #ifdef ONE_THREAD
  1389.   if (!(test_flags & TEST_NO_THREADS)) // For debugging under Linux
  1390. #endif
  1391.   {
  1392.     my_thread_end();
  1393.     pthread_exit(0);
  1394.   }
  1395.   DBUG_VOID_RETURN;
  1396. }
  1397. /* Start a cached thread. LOCK_thread_count is locked on entry */
  1398. static void start_cached_thread(THD *thd)
  1399. {
  1400.   thread_cache.append(thd);
  1401.   wake_thread++;
  1402.   thread_count++;
  1403.   pthread_cond_signal(&COND_thread_cache);
  1404. }
  1405. void flush_thread_cache()
  1406. {
  1407.   (void) pthread_mutex_lock(&LOCK_thread_count);
  1408.   kill_cached_threads++;
  1409.   while (cached_thread_count)
  1410.   {
  1411.     pthread_cond_broadcast(&COND_thread_cache);
  1412.     pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count);
  1413.   }
  1414.   kill_cached_threads--;
  1415.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  1416. }
  1417. /******************************************************************************
  1418.   Setup a signal thread with handles all signals.
  1419.   Because Linux doesn't support schemas use a mutex to check that
  1420.   the signal thread is ready before continuing
  1421. ******************************************************************************/
  1422. #if defined(__WIN__) || defined(OS2)
  1423. static void init_signals(void)
  1424. {
  1425.   int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
  1426.   for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
  1427.     signal( signals[i], kill_server) ;
  1428. #if defined(__WIN__)
  1429.   signal(SIGBREAK,SIG_IGN); //ignore SIGBREAK for NT
  1430. #else
  1431.   signal(SIGBREAK, kill_server);
  1432. #endif
  1433. }
  1434. static void start_signal_handler(void)
  1435. {
  1436.   // Save vm id of this process
  1437.   if (!opt_bootstrap)
  1438.     create_pid_file();
  1439. }
  1440. static void check_data_home(const char *path)
  1441. {}
  1442. #elif defined(__NETWARE__)
  1443. // down server event callback
  1444. void mysql_down_server_cb(void *, void *)
  1445. {
  1446.   event_flag = TRUE;  
  1447.   kill_server(0);
  1448. }
  1449. // destroy callback resources
  1450. void mysql_cb_destroy(void *)
  1451. {  
  1452.   UnRegisterEventNotification(eh);  // cleanup down event notification       
  1453.   NX_UNWRAP_INTERFACE(ref);
  1454.   /* Deregister NSS volume deactivation event */  
  1455.   NX_UNWRAP_INTERFACE(refneb);  
  1456.   if (neb_consumer_id)
  1457.     UnRegisterConsumer(neb_consumer_id, NULL);
  1458. }
  1459. // initialize callbacks
  1460. void mysql_cb_init()
  1461. {
  1462.   // register for down server event
  1463.   void *handle = getnlmhandle();
  1464.   rtag_t rt= AllocateResourceTag(handle, "MySQL Down Server Callback",
  1465.                                  EventSignature);
  1466.   NX_WRAP_INTERFACE((void *)mysql_down_server_cb, 2, (void **)&ref);
  1467.   eh= RegisterForEventNotification(rt, EVENT_PRE_DOWN_SERVER,
  1468.                                    EVENT_PRIORITY_APPLICATION,
  1469.                                    NULL, ref, NULL);
  1470.   /*
  1471.     Register for volume deactivation event
  1472.     Wrap the callback function, as it is called by non-LibC thread
  1473.   */
  1474.   (void *) NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
  1475.   registerwithneb();
  1476.   NXVmRegisterExitHandler(mysql_cb_destroy, NULL);  // clean-up
  1477. }
  1478. /* To get the name of the NetWare volume having MySQL data folder */
  1479. static void getvolumename()
  1480. {
  1481.   char *p;
  1482.   /*
  1483.     We assume that data path is already set.
  1484.     If not it won't come here. Terminate after volume name
  1485.   */
  1486.   if ((p= strchr(mysql_real_data_home, ':')))
  1487.     strmake(datavolname, mysql_real_data_home,
  1488.             (uint) (p - mysql_real_data_home));
  1489. }
  1490. /*
  1491.   Registering with NEB for NSS Volume Deactivation event
  1492. */
  1493. static void registerwithneb()
  1494. {
  1495.   ConsumerRegistrationInfo reg_info;
  1496.     
  1497.   /* Clear NEB registration structure */
  1498.   bzero((char*) &reg_info, sizeof(struct ConsumerRegistrationInfo));
  1499.   /* Fill the NEB consumer information structure */
  1500.   reg_info.CRIVersion= 1;               // NEB version
  1501.   /* NEB Consumer name */
  1502.   reg_info.CRIConsumerName= (BYTE *) "MySQL Database Server";
  1503.   /* Event of interest */
  1504.   reg_info.CRIEventName= (BYTE *) "NSS.ChangeVolState.Enter";
  1505.   reg_info.CRIUserParameter= NULL;     // Consumer Info
  1506.   reg_info.CRIEventFlags= 0;             // Event flags
  1507.   /* Consumer NLM handle */
  1508.   reg_info.CRIOwnerID= (LoadDefinitionStructure *)getnlmhandle();
  1509.   reg_info.CRIConsumerESR= NULL;     // No consumer ESR required
  1510.   reg_info.CRISecurityToken= 0;             // No security token for the event
  1511.   reg_info.CRIConsumerFlags= 0;             // SMP_ENABLED_BIT;
  1512.   reg_info.CRIFilterName= 0;             // No event filtering
  1513.   reg_info.CRIFilterDataLength= 0;          // No filtering data
  1514.   reg_info.CRIFilterData= 0;             // No filtering data
  1515.   /* Callback function for the event */
  1516.   (void *)reg_info.CRIConsumerCallback= (void *) refneb;
  1517.   reg_info.CRIOrder= 0;                     // Event callback order
  1518.   reg_info.CRIConsumerType= CHECK_CONSUMER; // Consumer type
  1519.   /* Register for the event with NEB */
  1520.   if (RegisterConsumer(&reg_info))
  1521.   {
  1522.     consoleprintf("Failed to register for NSS Volume Deactivation event n");
  1523.     return;
  1524.   }
  1525.   /* This ID is required for deregistration */
  1526.   neb_consumer_id= reg_info.CRIConsumerID;
  1527.   /* Get MySQL data volume name, stored in global variable datavolname */
  1528.   getvolumename();
  1529.   /*
  1530.     Get the NSS volume ID of the MySQL Data volume.
  1531.     Volume ID is stored in a global variable
  1532.   */
  1533.   getvolumeID((BYTE*) datavolname);
  1534. }
  1535. /*
  1536.   Callback for NSS Volume Deactivation event
  1537. */
  1538. ulong neb_event_callback(struct EventBlock *eblock)
  1539. {
  1540.   EventChangeVolStateEnter_s *voldata;
  1541.   extern bool nw_panic;
  1542.   voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData;
  1543.   /* Deactivation of a volume */
  1544.   if ((voldata->oldState == zVOLSTATE_ACTIVE &&
  1545.        voldata->newState == zVOLSTATE_DEACTIVE ||
  1546.        voldata->newState == zVOLSTATE_MAINTENANCE))
  1547.   {
  1548.     /*
  1549.       Ensure that we bring down MySQL server only for MySQL data
  1550.       volume deactivation
  1551.     */
  1552.     if (!memcmp(&voldata->volID, &datavolid, sizeof(VolumeID_t)))
  1553.     {
  1554.       consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server n");
  1555.       event_flag= TRUE;
  1556.       nw_panic = TRUE;
  1557.       event_flag= TRUE;
  1558.       kill_server(0);
  1559.  
  1560.     }
  1561.   }
  1562.   return 0;
  1563. }
  1564. /*
  1565.   Function to get NSS volume ID of the MySQL data
  1566. */
  1567. #define ADMIN_VOL_PATH "_ADMIN:/Volumes/"
  1568. static void getvolumeID(BYTE *volumeName)
  1569. {
  1570.   char path[zMAX_FULL_NAME];
  1571.   Key_t rootKey= 0, fileKey= 0;
  1572.   QUAD getInfoMask;
  1573.   zInfo_s info;
  1574.   STATUS status;
  1575.   /* Get the root key */
  1576.   if ((status= zRootKey(0, &rootKey)) != zOK)
  1577.   {
  1578.     consoleprintf("nGetNSSVolumeProperties - Failed to get root key, status: %dn.", (int) status);
  1579.     goto exit;
  1580.   }
  1581.   /*
  1582.     Get the file key. This is the key to the volume object in the
  1583.     NSS admin volumes directory.
  1584.   */
  1585.   strxmov(path, (const char *) ADMIN_VOL_PATH, (const char *) volumeName,
  1586.           NullS);
  1587.   if ((status= zOpen(rootKey, zNSS_TASK, zNSPACE_LONG|zMODE_UTF8, 
  1588.                      (BYTE *) path, zRR_READ_ACCESS, &fileKey)) != zOK)
  1589.   {
  1590.     consoleprintf("nGetNSSVolumeProperties - Failed to get file, status: %dn.", (int) status);
  1591.     goto exit;
  1592.   }
  1593.   getInfoMask= zGET_IDS | zGET_VOLUME_INFO ;
  1594.   if ((status= zGetInfo(fileKey, getInfoMask, sizeof(info), 
  1595.                         zINFO_VERSION_A, &info)) != zOK)
  1596.   {
  1597.     consoleprintf("nGetNSSVolumeProperties - Failed in zGetInfo, status: %dn.", (int) status);
  1598.     goto exit;
  1599.   }
  1600.   /* Copy the data to global variable */
  1601.   datavolid.timeLow= info.vol.volumeID.timeLow;
  1602.   datavolid.timeMid= info.vol.volumeID.timeMid;
  1603.   datavolid.timeHighAndVersion= info.vol.volumeID.timeHighAndVersion;
  1604.   datavolid.clockSeqHighAndReserved= info.vol.volumeID.clockSeqHighAndReserved;
  1605.   datavolid.clockSeqLow= info.vol.volumeID.clockSeqLow;
  1606.   /* This is guranteed to be 6-byte length (but sizeof() would be better) */
  1607.   memcpy(datavolid.node, info.vol.volumeID.node, (unsigned int) 6);
  1608. exit:
  1609.   if (rootKey)
  1610.     zClose(rootKey);
  1611.   if (fileKey)
  1612.     zClose(fileKey);
  1613. }
  1614. static void init_signals(void)
  1615. {
  1616.   int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT};
  1617.   for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
  1618.     signal(signals[i], kill_server);
  1619.   mysql_cb_init();  // initialize callbacks
  1620. }
  1621. static void start_signal_handler(void)
  1622. {
  1623.   // Save vm id of this process
  1624.   if (!opt_bootstrap)
  1625.     create_pid_file();
  1626.   // no signal handler
  1627. }
  1628. /*
  1629.   Warn if the data is on a Traditional volume
  1630.   NOTE
  1631.     Already done by mysqld_safe
  1632. */
  1633. static void check_data_home(const char *path)
  1634. {
  1635. }
  1636. #elif defined(__EMX__)
  1637. static void sig_reload(int signo)
  1638. {
  1639.  // Flush everything
  1640.   reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, NULL);
  1641.   signal(signo, SIG_ACK);
  1642. }
  1643. static void sig_kill(int signo)
  1644. {
  1645.   if (!kill_in_progress)
  1646.   {
  1647.     abort_loop=1; // mark abort for threads
  1648.     kill_server((void*) signo);
  1649.   }
  1650.   signal(signo, SIG_ACK);
  1651. }
  1652. static void init_signals(void)
  1653. {
  1654.   signal(SIGQUIT, sig_kill);
  1655.   signal(SIGKILL, sig_kill);
  1656.   signal(SIGTERM, sig_kill);
  1657.   signal(SIGINT,  sig_kill);
  1658.   signal(SIGHUP,  sig_reload); // Flush everything
  1659.   signal(SIGALRM, SIG_IGN);
  1660.   signal(SIGBREAK,SIG_IGN);
  1661.   signal_thread = pthread_self();
  1662. }
  1663. static void start_signal_handler(void)
  1664. {}
  1665. static void check_data_home(const char *path)
  1666. {}
  1667. #else /* if ! __WIN__ && ! __EMX__ */
  1668. #ifdef HAVE_LINUXTHREADS
  1669. #define UNSAFE_DEFAULT_LINUX_THREADS 200
  1670. #endif
  1671. extern "C" sig_handler handle_segfault(int sig)
  1672. {
  1673.   THD *thd=current_thd;
  1674.   /*
  1675.     Strictly speaking, one needs a mutex here
  1676.     but since we have got SIGSEGV already, things are a mess
  1677.     so not having the mutex is not as bad as possibly using a buggy
  1678.     mutex - so we keep things simple
  1679.   */
  1680.   if (segfaulted)
  1681.   {
  1682.     fprintf(stderr, "Fatal signal %d while backtracingn", sig);
  1683.     exit(1);
  1684.   }
  1685.   segfaulted = 1;
  1686.   fprintf(stderr,"
  1687. mysqld got signal %d;n
  1688. This could be because you hit a bug. It is also possible that this binaryn
  1689. or one of the libraries it was linked against is corrupt, improperly built,n
  1690. or misconfigured. This error can also be caused by malfunctioning hardware.n",
  1691.   sig);
  1692.   fprintf(stderr, "
  1693. We will try our best to scrape up some info that will hopefully help diagnosen
  1694. the problem, but since we have already crashed, something is definitely wrongn
  1695. and this may fail.nn");
  1696.   fprintf(stderr, "key_buffer_size=%lun", 
  1697.           (ulong) dflt_key_cache->key_cache_mem_size);
  1698.   fprintf(stderr, "read_buffer_size=%ldn", global_system_variables.read_buff_size);
  1699.   fprintf(stderr, "max_used_connections=%ldn", max_used_connections);
  1700.   fprintf(stderr, "max_connections=%ldn", max_connections);
  1701.   fprintf(stderr, "threads_connected=%dn", thread_count);
  1702.   fprintf(stderr, "It is possible that mysqld could use up to n
  1703. key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld Kn
  1704. bytes of memoryn", ((ulong) dflt_key_cache->key_cache_mem_size +
  1705.      (global_system_variables.read_buff_size +
  1706.       global_system_variables.sortbuff_size) *
  1707.      max_connections)/ 1024);
  1708.   fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.nn");
  1709. #if defined(HAVE_LINUXTHREADS)
  1710.   if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
  1711.   {
  1712.     fprintf(stderr, "
  1713. You seem to be running 32-bit Linux and have %d concurrent connections.n
  1714. If you have not changed STACK_SIZE in LinuxThreads and built the binary n
  1715. yourself, LinuxThreads is quite likely to steal a part of the global heap forn
  1716. the thread stack. Please read http://www.mysql.com/doc/en/Linux.htmlnn",
  1717.     thread_count);
  1718.   }
  1719. #endif /* HAVE_LINUXTHREADS */
  1720. #ifdef HAVE_STACKTRACE
  1721.   if (!(test_flags & TEST_NO_STACKTRACE))
  1722.   {
  1723.     fprintf(stderr,"thd=%pn",thd);
  1724.     print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
  1725.      thread_stack);
  1726.   }
  1727.   if (thd)
  1728.   {
  1729.     fprintf(stderr, "Trying to get some variables.n
  1730. Some pointers may be invalid and cause the dump to abort...n");
  1731.     safe_print_str("thd->query", thd->query, 1024);
  1732.     fprintf(stderr, "thd->thread_id=%ldn", thd->thread_id);
  1733.   }
  1734.   fprintf(stderr, "
  1735. The manual page at http://www.mysql.com/doc/en/Crashing.html containsn
  1736. information that should help you find out what is causing the crash.n");
  1737.   fflush(stderr);
  1738. #endif /* HAVE_STACKTRACE */
  1739. #ifdef HAVE_INITGROUPS
  1740.   if (calling_initgroups)
  1741.     fprintf(stderr, "n
  1742. This crash occured while the server was calling initgroups(). This isn
  1743. often due to the use of a mysqld that is statically linked against glibcn
  1744. and configured to use LDAP in /etc/nsswitch.conf. You will need to eithern
  1745. upgrade to a version of glibc that does not have this problem (2.3.4 orn
  1746. later when used with nscd), disable LDAP in your nsswitch.conf, or use an
  1747. mysqld that is not statically linked.n");
  1748. #endif
  1749.  if (test_flags & TEST_CORE_ON_SIGNAL)
  1750.  {
  1751.    fprintf(stderr, "Writing a core filen");
  1752.    fflush(stderr);
  1753.    write_core(sig);
  1754.  }
  1755.  exit(1);
  1756. }
  1757. #ifndef SA_RESETHAND
  1758. #define SA_RESETHAND 0
  1759. #endif
  1760. #ifndef SA_NODEFER
  1761. #define SA_NODEFER 0
  1762. #endif
  1763. static void init_signals(void)
  1764. {
  1765.   sigset_t set;
  1766.   struct sigaction sa;
  1767.   DBUG_ENTER("init_signals");
  1768.   if (test_flags & TEST_SIGINT)
  1769.     my_sigset(THR_KILL_SIGNAL,end_thread_signal);
  1770.   my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
  1771.   if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
  1772.   {
  1773.     sa.sa_flags = SA_RESETHAND | SA_NODEFER;
  1774.     sigemptyset(&sa.sa_mask);
  1775.     sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
  1776.     init_stacktrace();
  1777. #if defined(__amiga__)
  1778.     sa.sa_handler=(void(*)())handle_segfault;
  1779. #else
  1780.     sa.sa_handler=handle_segfault;
  1781. #endif
  1782.     sigaction(SIGSEGV, &sa, NULL);
  1783.     sigaction(SIGABRT, &sa, NULL);
  1784. #ifdef SIGBUS
  1785.     sigaction(SIGBUS, &sa, NULL);
  1786. #endif
  1787.     sigaction(SIGILL, &sa, NULL);
  1788.     sigaction(SIGFPE, &sa, NULL);
  1789.   }
  1790. #ifdef HAVE_GETRLIMIT
  1791.   if (test_flags & TEST_CORE_ON_SIGNAL)
  1792.   {
  1793.     /* Change limits so that we will get a core file */
  1794.     STRUCT_RLIMIT rl;
  1795.     rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
  1796.     if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
  1797.       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");
  1798.   }
  1799. #endif
  1800.   (void) sigemptyset(&set);
  1801.   my_sigset(SIGPIPE,SIG_IGN);
  1802.   sigaddset(&set,SIGPIPE);
  1803.   sigaddset(&set,SIGINT);
  1804. #ifndef IGNORE_SIGHUP_SIGQUIT
  1805.   sigaddset(&set,SIGQUIT);
  1806.   sigaddset(&set,SIGHUP);
  1807. #endif
  1808.   sigaddset(&set,SIGTERM);
  1809.   /* Fix signals if blocked by parents (can happen on Mac OS X) */
  1810.   sigemptyset(&sa.sa_mask);
  1811.   sa.sa_flags = 0;
  1812.   sa.sa_handler = print_signal_warning;
  1813.   sigaction(SIGTERM, &sa, (struct sigaction*) 0);
  1814.   sa.sa_flags = 0;
  1815.   sa.sa_handler = print_signal_warning;
  1816.   sigaction(SIGHUP, &sa, (struct sigaction*) 0);
  1817. #ifdef SIGTSTP
  1818.   sigaddset(&set,SIGTSTP);
  1819. #endif
  1820.   sigaddset(&set,THR_SERVER_ALARM);
  1821.   if (test_flags & TEST_SIGINT)
  1822.     sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
  1823.   sigdelset(&set,THR_CLIENT_ALARM); // For alarms
  1824.   sigprocmask(SIG_SETMASK,&set,NULL);
  1825.   pthread_sigmask(SIG_SETMASK,&set,NULL);
  1826.   DBUG_VOID_RETURN;
  1827. }
  1828. #ifndef EMBEDDED_LIBRARY
  1829. static void start_signal_handler(void)
  1830. {
  1831.   int error;
  1832.   pthread_attr_t thr_attr;
  1833.   DBUG_ENTER("start_signal_handler");
  1834.   (void) pthread_attr_init(&thr_attr);
  1835. #if !defined(HAVE_DEC_3_2_THREADS)
  1836.   pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
  1837.   (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
  1838.   if (!(opt_specialflag & SPECIAL_NO_PRIOR))
  1839.     my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
  1840.   pthread_attr_setstacksize(&thr_attr,thread_stack);
  1841. #endif
  1842.   (void) pthread_mutex_lock(&LOCK_thread_count);
  1843.   if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
  1844.   {
  1845.     sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
  1846.     error,errno);
  1847.     exit(1);
  1848.   }
  1849.   (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
  1850.   pthread_mutex_unlock(&LOCK_thread_count);
  1851.   (void) pthread_attr_destroy(&thr_attr);
  1852.   DBUG_VOID_RETURN;
  1853. }
  1854. /* This threads handles all signals and alarms */
  1855. /* ARGSUSED */
  1856. extern "C" void *signal_hand(void *arg __attribute__((unused)))
  1857. {
  1858.   sigset_t set;
  1859.   int sig;
  1860.   my_thread_init(); // Init new thread
  1861.   DBUG_ENTER("signal_hand");
  1862.   signal_thread_in_use= 1;
  1863.   /*
  1864.     Setup alarm handler
  1865.     This should actually be '+ max_number_of_slaves' instead of +10,
  1866.     but the +10 should be quite safe.
  1867.   */
  1868.   init_thr_alarm(max_connections +
  1869.  global_system_variables.max_insert_delayed_threads + 10);
  1870. #if SIGINT != THR_KILL_SIGNAL
  1871.   if (test_flags & TEST_SIGINT)
  1872.   {
  1873.     (void) sigemptyset(&set); // Setup up SIGINT for debug
  1874.     (void) sigaddset(&set,SIGINT); // For debugging
  1875.     (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
  1876.   }
  1877. #endif
  1878.   (void) sigemptyset(&set); // Setup up SIGINT for debug
  1879. #ifdef USE_ONE_SIGNAL_HAND
  1880.   (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
  1881. #endif
  1882. #ifndef IGNORE_SIGHUP_SIGQUIT
  1883.   (void) sigaddset(&set,SIGQUIT);
  1884. #if THR_CLIENT_ALARM != SIGHUP
  1885.   (void) sigaddset(&set,SIGHUP);
  1886. #endif
  1887. #endif
  1888.   (void) sigaddset(&set,SIGTERM);
  1889.   (void) sigaddset(&set,SIGTSTP);
  1890.   /* Save pid to this process (or thread on Linux) */
  1891.   if (!opt_bootstrap)
  1892.     create_pid_file();
  1893. #ifdef HAVE_STACK_TRACE_ON_SEGV
  1894.   if (opt_do_pstack)
  1895.   {
  1896.     sprintf(pstack_file_name,"mysqld-%lu-%%d-%%d.backtrace", (ulong)getpid());
  1897.     pstack_install_segv_action(pstack_file_name);
  1898.   }
  1899. #endif /* HAVE_STACK_TRACE_ON_SEGV */
  1900.   /*
  1901.     signal to start_signal_handler that we are ready
  1902.     This works by waiting for start_signal_handler to free mutex,
  1903.     after which we signal it that we are ready.
  1904.     At this pointer there is no other threads running, so there
  1905.     should not be any other pthread_cond_signal() calls.
  1906.   */
  1907.   (void) pthread_mutex_lock(&LOCK_thread_count);
  1908.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  1909.   (void) pthread_cond_broadcast(&COND_thread_count);
  1910.   (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
  1911.   for (;;)
  1912.   {
  1913.     int error; // Used when debugging
  1914.     if (shutdown_in_progress && !abort_loop)
  1915.     {
  1916.       sig= SIGTERM;
  1917.       error=0;
  1918.     }
  1919.     else
  1920.       while ((error=my_sigwait(&set,&sig)) == EINTR) ;
  1921.     if (cleanup_done)
  1922.     {
  1923.       DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
  1924.       my_thread_end();
  1925.       signal_thread_in_use= 0;
  1926.       pthread_exit(0); // Safety
  1927.     }
  1928.     switch (sig) {
  1929.     case SIGTERM:
  1930.     case SIGQUIT:
  1931.     case SIGKILL:
  1932. #ifdef EXTRA_DEBUG
  1933.       sql_print_information("Got signal %d to shutdown mysqld",sig);
  1934. #endif
  1935.       DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
  1936.       if (!abort_loop)
  1937.       {
  1938. abort_loop=1; // mark abort for threads
  1939. #ifdef USE_ONE_SIGNAL_HAND
  1940. pthread_t tmp;
  1941. if (!(opt_specialflag & SPECIAL_NO_PRIOR))
  1942.   my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
  1943. if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
  1944.    (void*) sig))
  1945.   sql_print_error("Can't create thread to kill server");
  1946. #else
  1947. kill_server((void*) sig); // MIT THREAD has a alarm thread
  1948. #endif
  1949.       }
  1950.       break;
  1951.     case SIGHUP:
  1952.       if (!abort_loop)
  1953.       {
  1954. mysql_print_status((THD*) 0); // Print some debug info
  1955. reload_acl_and_cache((THD*) 0,
  1956.      (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
  1957.       REFRESH_STATUS | REFRESH_GRANT |
  1958.       REFRESH_THREADS | REFRESH_HOSTS),
  1959.      (TABLE_LIST*) 0, NULL); // Flush logs
  1960.       }
  1961.       break;
  1962. #ifdef USE_ONE_SIGNAL_HAND
  1963.     case THR_SERVER_ALARM:
  1964.       process_alarm(sig); // Trigger alarms.
  1965.       break;
  1966. #endif
  1967.     default:
  1968. #ifdef EXTRA_DEBUG
  1969.       sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
  1970. #endif
  1971.       break; /* purecov: tested */
  1972.     }
  1973.   }
  1974.   return(0); /* purecov: deadcode */
  1975. }
  1976. #endif /*!EMBEDDED_LIBRARY*/
  1977. static void check_data_home(const char *path)
  1978. {}
  1979. #endif /* __WIN__*/
  1980. /*
  1981.   All global error messages are sent here where the first one is stored for
  1982.   the client
  1983. */
  1984. /* ARGSUSED */
  1985. extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
  1986. {
  1987.   THD *thd;
  1988.   DBUG_ENTER("my_message_sql");
  1989.   DBUG_PRINT("error", ("Message: '%s'", str));
  1990.   if ((thd= current_thd))
  1991.   {
  1992.     /*
  1993.       thd->lex->current_select == 0 if lex structure is not inited
  1994.       (not query command (COM_QUERY))
  1995.     */
  1996.     if (thd->lex->current_select &&
  1997. thd->lex->current_select->no_error && !thd->is_fatal_error)
  1998.     {
  1999.       DBUG_PRINT("error", ("Error converted to warning: current_select: no_error %d  fatal_error: %d",
  2000.                            (thd->lex->current_select ?
  2001.                             thd->lex->current_select->no_error : 0),
  2002.                            (int) thd->is_fatal_error));
  2003.                            
  2004.       push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
  2005.     }
  2006.     else
  2007.     {
  2008.       NET *net= &thd->net;
  2009.       net->report_error= 1;
  2010.       if (!net->last_error[0]) // Return only first message
  2011.       {
  2012. strmake(net->last_error, str, sizeof(net->last_error)-1);
  2013. net->last_errno= error ? error : ER_UNKNOWN_ERROR;
  2014.       }
  2015.     }
  2016.   }
  2017.   if (!thd || MyFlags & ME_NOREFRESH)
  2018.     sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
  2019.   DBUG_RETURN(0);
  2020. }
  2021. #ifdef __WIN__
  2022. struct utsname
  2023. {
  2024.   char nodename[FN_REFLEN];
  2025. };
  2026. int uname(struct utsname *a)
  2027. {
  2028.   return -1;
  2029. }
  2030. extern "C" pthread_handler_decl(handle_shutdown,arg)
  2031. {
  2032.   MSG msg;
  2033.   my_thread_init();
  2034.   /* this call should create the message queue for this thread */
  2035.   PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
  2036. #if !defined(EMBEDDED_LIBRARY)
  2037.   if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
  2038. #endif /* EMBEDDED_LIBRARY */
  2039.      kill_server(MYSQL_KILL_SIGNAL);
  2040.   return 0;
  2041. }
  2042. int STDCALL handle_kill(ulong ctrl_type)
  2043. {
  2044.   if (ctrl_type == CTRL_CLOSE_EVENT ||
  2045.       ctrl_type == CTRL_SHUTDOWN_EVENT)
  2046.   {
  2047.     kill_server(MYSQL_KILL_SIGNAL);
  2048.     return TRUE;
  2049.   }
  2050.   return FALSE;
  2051. }
  2052. #endif
  2053. #ifdef OS2
  2054. extern "C" pthread_handler_decl(handle_shutdown,arg)
  2055. {
  2056.   my_thread_init();
  2057.   // wait semaphore
  2058.   pthread_cond_wait( &eventShutdown, NULL);
  2059.   // close semaphore and kill server
  2060.   pthread_cond_destroy( &eventShutdown);
  2061.   /*
  2062.     Exit main loop on main thread, so kill will be done from
  2063.     main thread (this is thread 2)
  2064.   */
  2065.   abort_loop = 1;
  2066.   // unblock select()
  2067.   so_cancel(ip_sock);
  2068.   so_cancel(unix_sock);
  2069.   return 0;
  2070. }
  2071. #endif
  2072. const char *load_default_groups[]= { 
  2073. #ifdef HAVE_NDBCLUSTER_DB
  2074. "mysql_cluster",
  2075. #endif
  2076. "mysqld","server",MYSQL_BASE_VERSION,0,0};
  2077. static const int load_default_groups_sz=
  2078. sizeof(load_default_groups)/sizeof(load_default_groups[0]);
  2079. bool open_log(MYSQL_LOG *log, const char *hostname,
  2080.       const char *opt_name, const char *extension,
  2081.       const char *index_file_name,
  2082.       enum_log_type type, bool read_append,
  2083.       bool no_auto_events, ulong max_size)
  2084. {
  2085.   char tmp[FN_REFLEN];
  2086.   if (!opt_name || !opt_name[0])
  2087.   {
  2088.     /*
  2089.       TODO: The following should be using fn_format();  We just need to
  2090.       first change fn_format() to cut the file name if it's too long.
  2091.     */
  2092.     strmake(tmp,hostname,FN_REFLEN-5);
  2093.     strmov(fn_ext(tmp),extension);
  2094.     opt_name=tmp;
  2095.   }
  2096.   // get rid of extension if the log is binary to avoid problems
  2097.   if (type == LOG_BIN)
  2098.   {
  2099.     char *p = fn_ext(opt_name);
  2100.     uint length=(uint) (p-opt_name);
  2101.     strmake(tmp,opt_name,min(length,FN_REFLEN));
  2102.     opt_name=tmp;
  2103.   }
  2104.   return log->open(opt_name, type, 0, index_file_name,
  2105.    (read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
  2106.    no_auto_events, max_size);
  2107. }
  2108. /*
  2109.   Initialize one of the global date/time format variables
  2110.   SYNOPSIS
  2111.     init_global_datetime_format()
  2112.     format_type What kind of format should be supported
  2113.     var_ptr Pointer to variable that should be updated
  2114.   
  2115.   NOTES
  2116.     The default value is taken from either opt_date_time_formats[] or
  2117.     the ISO format (ANSI SQL)
  2118.   RETURN
  2119.     0 ok
  2120.     1 error
  2121. */
  2122. bool init_global_datetime_format(timestamp_type format_type,
  2123.  DATE_TIME_FORMAT **var_ptr)
  2124. {
  2125.   /* Get command line option */
  2126.   const char *str= opt_date_time_formats[format_type];
  2127.   if (!str) // No specified format
  2128.   {
  2129.     str= get_date_time_format_str(&known_date_time_formats[ISO_FORMAT],
  2130.   format_type);
  2131.     /*
  2132.       Set the "command line" option to point to the generated string so
  2133.       that we can set global formats back to default
  2134.     */
  2135.     opt_date_time_formats[format_type]= str;
  2136.   }
  2137.   if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str))))
  2138.   {
  2139.     fprintf(stderr, "Wrong date/time format specifier: %sn", str);
  2140.     return 1;
  2141.   }
  2142.   return 0;
  2143. }
  2144. static int init_common_variables(const char *conf_file_name, int argc,
  2145.  char **argv, const char **groups)
  2146. {
  2147.   umask(((~my_umask) & 0666));
  2148.   tzset(); // Set tzname
  2149.   max_system_variables.pseudo_thread_id= (ulong)~0;
  2150.   start_time=time((time_t*) 0);
  2151.   if (init_thread_environment())
  2152.     return 1;
  2153.   mysql_init_variables();
  2154. #ifdef OS2
  2155.   {
  2156.     // fix timezone for daylight saving
  2157.     struct tm *ts = localtime(&start_time);
  2158.     if (ts->tm_isdst > 0)
  2159.       _timezone -= 3600;
  2160.   }
  2161. #endif
  2162. #ifdef HAVE_TZNAME
  2163.   {
  2164.     struct tm tm_tmp;
  2165.     localtime_r(&start_time,&tm_tmp);
  2166.     strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
  2167.             sizeof(system_time_zone)-1);
  2168.  }
  2169. #endif
  2170.   /*
  2171.     We set SYSTEM time zone as reasonable default and 
  2172.     also for failure of my_tz_init() and bootstrap mode.
  2173.     If user explicitly set time zone with --default-time-zone
  2174.     option we will change this value in my_tz_init().
  2175.   */
  2176.   global_system_variables.time_zone= my_tz_SYSTEM;
  2177.   
  2178.   /*
  2179.     Init mutexes for the global MYSQL_LOG objects.
  2180.     As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
  2181.     global MYSQL_LOGs in their constructors, because then they would be inited
  2182.     before MY_INIT(). So we do it here.
  2183.   */
  2184.   mysql_log.init_pthread_objects();
  2185.   mysql_update_log.init_pthread_objects();
  2186.   mysql_slow_log.init_pthread_objects();
  2187.   mysql_bin_log.init_pthread_objects();
  2188.   
  2189.   if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
  2190.     strmov(glob_hostname,"mysql");
  2191.   strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
  2192.   strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
  2193.   load_defaults(conf_file_name, groups, &argc, &argv);
  2194.   defaults_argv=argv;
  2195.   get_options(argc,argv);
  2196.   set_server_version();
  2197.   DBUG_PRINT("info",("%s  Ver %s for %s on %sn",my_progname,
  2198.      server_version, SYSTEM_TYPE,MACHINE_TYPE));
  2199.   /* connections and databases needs lots of files */
  2200.   {
  2201.     uint files, wanted_files;
  2202.     wanted_files= 10+(uint) max(max_connections*5,
  2203.  max_connections+table_cache_size*2);
  2204.     set_if_bigger(wanted_files, open_files_limit);
  2205.     files= my_set_max_open_files(wanted_files);
  2206.     if (files < wanted_files)
  2207.     {
  2208.       if (!open_files_limit)
  2209.       {
  2210. max_connections= (ulong) min((files-10),max_connections);
  2211. table_cache_size= (ulong) max((files-10-max_connections)/2,64);
  2212. DBUG_PRINT("warning",
  2213.    ("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
  2214.     files, max_connections, table_cache_size));
  2215. if (global_system_variables.log_warnings)
  2216.   sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
  2217. files, max_connections, table_cache_size);
  2218.       }
  2219.       else if (global_system_variables.log_warnings)
  2220. sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
  2221.     }
  2222.     open_files_limit= files;
  2223.   }
  2224.   unireg_init(opt_specialflag); /* Set up extern variabels */
  2225.   if (init_errmessage()) /* Read error messages from file */
  2226.     return 1;
  2227.   init_client_errs();
  2228.   lex_init();
  2229.   item_init();
  2230.   set_var_init();
  2231.   mysys_uses_curses=0;
  2232. #ifdef USE_REGEX
  2233.   my_regex_init(&my_charset_latin1);
  2234. #endif
  2235.   if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
  2236.     MY_CS_PRIMARY,
  2237.     MYF(MY_WME))))
  2238.     return 1;
  2239.   if (default_collation_name)
  2240.   {
  2241.     CHARSET_INFO *default_collation;
  2242.     default_collation= get_charset_by_name(default_collation_name, MYF(0));
  2243.     if (!default_collation)
  2244.     {
  2245.       sql_print_error(ER(ER_UNKNOWN_COLLATION), default_collation_name);
  2246.       return 1;
  2247.     }
  2248.     if (!my_charset_same(default_charset_info, default_collation))
  2249.     {
  2250.       sql_print_error(ER(ER_COLLATION_CHARSET_MISMATCH),
  2251.       default_collation_name,
  2252.       default_charset_info->csname);
  2253.       return 1;
  2254.     }
  2255.     default_charset_info= default_collation;
  2256.   }
  2257.   /* Set collactions that depends on the default collation */
  2258.   global_system_variables.collation_server=  default_charset_info;
  2259.   global_system_variables.collation_database=  default_charset_info;
  2260.   global_system_variables.collation_connection=  default_charset_info;
  2261.   global_system_variables.character_set_results= default_charset_info;
  2262.   global_system_variables.character_set_client= default_charset_info;
  2263.   global_system_variables.collation_connection= default_charset_info;
  2264.   sys_init_connect.value_length= 0;
  2265.   if ((sys_init_connect.value= opt_init_connect))
  2266.     sys_init_connect.value_length= strlen(opt_init_connect);
  2267.   else
  2268.     sys_init_connect.value=my_strdup("",MYF(0));
  2269.   sys_init_slave.value_length= 0;
  2270.   if ((sys_init_slave.value= opt_init_slave))
  2271.     sys_init_slave.value_length= strlen(opt_init_slave);
  2272.   else
  2273.     sys_init_slave.value=my_strdup("",MYF(0));
  2274.   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
  2275.     return 1;
  2276.   if (my_dbopt_init())
  2277.     return 1;
  2278.   /*
  2279.     Ensure that lower_case_table_names is set on system where we have case
  2280.     insensitive names.  If this is not done the users MyISAM tables will
  2281.     get corrupted if accesses with names of different case.
  2282.   */
  2283.   DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
  2284.   if (!lower_case_table_names &&
  2285.       (lower_case_file_system=
  2286.        (test_if_case_insensitive(mysql_real_data_home) == 1)))
  2287.   {
  2288.     if (lower_case_table_names_used)
  2289.     {
  2290.       if (global_system_variables.log_warnings)
  2291. sql_print_warning("
  2292. You have forced lower_case_table_names to 0 through a command-line 
  2293. option, even though your file system '%s' is case insensitive.  This means 
  2294. that you can corrupt a MyISAM table by accessing it with different cases. 
  2295. You should consider changing lower_case_table_names to 1 or 2",
  2296. mysql_real_data_home);
  2297.     }
  2298.     else
  2299.     {
  2300.       if (global_system_variables.log_warnings)
  2301. sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
  2302.       lower_case_table_names= 2;
  2303.     }
  2304.   }
  2305.   else if (lower_case_table_names == 2 &&
  2306.            !(lower_case_file_system=
  2307.              (test_if_case_insensitive(mysql_real_data_home) == 1)))
  2308.   {
  2309.     if (global_system_variables.log_warnings)
  2310.       sql_print_warning("lower_case_table_names was set to 2, even though your "
  2311.                         "the file system '%s' is case sensitive.  Now setting "
  2312.                         "lower_case_table_names to 0 to avoid future problems.",
  2313. mysql_real_data_home);
  2314.     lower_case_table_names= 0;
  2315.   }
  2316.   /* Reset table_alias_charset, now that lower_case_table_names is set. */
  2317.   table_alias_charset= (lower_case_table_names ?
  2318. files_charset_info :
  2319. &my_charset_bin);
  2320.   return 0;
  2321. }
  2322. static int init_thread_environment()
  2323. {
  2324.   (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
  2325.   (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
  2326.   (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
  2327.   (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
  2328.   (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
  2329.   (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
  2330.   (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
  2331.   (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
  2332.   (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
  2333.   (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
  2334.   (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
  2335.   (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
  2336.   (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
  2337.   (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
  2338.   (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
  2339.   (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
  2340.   (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
  2341.   (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
  2342. #ifdef HAVE_OPENSSL
  2343.   (void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
  2344. #endif
  2345.   (void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
  2346.   (void) my_rwlock_init(&LOCK_sys_init_slave, NULL);
  2347.   (void) my_rwlock_init(&LOCK_grant, NULL);
  2348.   (void) pthread_cond_init(&COND_thread_count,NULL);
  2349.   (void) pthread_cond_init(&COND_refresh,NULL);
  2350.   (void) pthread_cond_init(&COND_thread_cache,NULL);
  2351.   (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
  2352.   (void) pthread_cond_init(&COND_manager,NULL);
  2353. #ifdef HAVE_REPLICATION
  2354.   (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
  2355.   (void) pthread_cond_init(&COND_rpl_status, NULL);
  2356. #endif
  2357.   /* Parameter for threads created for connections */
  2358.   (void) pthread_attr_init(&connection_attrib);
  2359.   (void) pthread_attr_setdetachstate(&connection_attrib,
  2360.      PTHREAD_CREATE_DETACHED);
  2361.   pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
  2362.   if (!(opt_specialflag & SPECIAL_NO_PRIOR))
  2363.     my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
  2364.   if (pthread_key_create(&THR_THD,NULL) ||
  2365.       pthread_key_create(&THR_MALLOC,NULL))
  2366.   {
  2367.     sql_print_error("Can't create thread-keys");
  2368.     return 1;
  2369.   }
  2370. #ifdef HAVE_OPENSSL
  2371.   openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
  2372.                                                      sizeof(openssl_lock_t));
  2373.   for (int i= 0; i < CRYPTO_num_locks(); ++i)
  2374.     (void) my_rwlock_init(&openssl_stdlocks[i].lock, NULL); 
  2375.   CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
  2376.   CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
  2377.   CRYPTO_set_dynlock_lock_callback(openssl_lock);
  2378.   CRYPTO_set_locking_callback(openssl_lock_function);
  2379.   CRYPTO_set_id_callback(openssl_id_function);
  2380. #endif
  2381.   return 0;
  2382. }
  2383. #ifdef HAVE_OPENSSL
  2384. static unsigned long openssl_id_function()
  2385.   return (unsigned long) pthread_self();
  2386. static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
  2387.   openssl_lock_t *lock= new openssl_lock_t;
  2388.   my_rwlock_init(&lock->lock, NULL);
  2389.   return lock;
  2390. }
  2391. static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file, 
  2392.     int line)
  2393. {
  2394.   rwlock_destroy(&lock->lock);
  2395.   delete lock;
  2396. }
  2397. static void openssl_lock_function(int mode, int n, const char *file, int line)
  2398. {
  2399.   if (n < 0 || n > CRYPTO_num_locks())
  2400.   {
  2401.     /* Lock number out of bounds. */
  2402.     sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
  2403.     abort();
  2404.   }
  2405.   openssl_lock(mode, &openssl_stdlocks[n], file, line);
  2406. }
  2407. static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, 
  2408.  int line)
  2409. {
  2410.   int err;
  2411.   char const *what;
  2412.   switch (mode) {
  2413.   case CRYPTO_LOCK|CRYPTO_READ:
  2414.     what = "read lock";
  2415.     err = rw_rdlock(&lock->lock);
  2416.     break;
  2417.   case CRYPTO_LOCK|CRYPTO_WRITE:
  2418.     what = "write lock";
  2419.     err = rw_wrlock(&lock->lock);
  2420.     break;
  2421.   case CRYPTO_UNLOCK|CRYPTO_READ:
  2422.   case CRYPTO_UNLOCK|CRYPTO_WRITE:
  2423.     what = "unlock";
  2424.     err = rw_unlock(&lock->lock);
  2425.     break;
  2426.   default:
  2427.     /* Unknown locking mode. */
  2428.     sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
  2429.     abort();
  2430.   }
  2431.   if (err) 
  2432.   {
  2433.     sql_print_error("Fatal: can't %s OpenSSL %s lock", what);
  2434.     abort();
  2435.   }
  2436. }
  2437. #endif /* HAVE_OPENSSL */
  2438. static void init_ssl()
  2439. {
  2440. #ifdef HAVE_OPENSSL
  2441.   if (opt_use_ssl)
  2442.   {
  2443.     /* having ssl_acceptor_fd != 0 signals the use of SSL */
  2444.     ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
  2445.   opt_ssl_ca, opt_ssl_capath,
  2446.   opt_ssl_cipher);
  2447.     DBUG_PRINT("info",("ssl_acceptor_fd: %lx", (long) ssl_acceptor_fd));
  2448.     if (!ssl_acceptor_fd)
  2449.       opt_use_ssl = 0;
  2450.   }
  2451.   if (des_key_file)
  2452.     load_des_key_file(des_key_file);
  2453. #endif /* HAVE_OPENSSL */
  2454. }
  2455. static int init_server_components()
  2456. {
  2457.   DBUG_ENTER("init_server_components");
  2458.   if (table_cache_init() || hostname_cache_init())
  2459.     unireg_abort(1);
  2460.   query_cache_result_size_limit(query_cache_limit);
  2461.   query_cache_set_min_res_unit(query_cache_min_res_unit);
  2462.   query_cache_init();
  2463.   query_cache_resize(query_cache_size);
  2464.   randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
  2465.   reset_floating_point_exceptions();
  2466.   init_thr_lock();
  2467. #ifdef HAVE_REPLICATION
  2468.   init_slave_list();
  2469. #endif
  2470.   /* Setup log files */
  2471.   if (opt_log)
  2472.     open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
  2473.      LOG_NORMAL, 0, 0, 0);
  2474.   if (opt_update_log)
  2475.   {
  2476.     open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
  2477.      NullS, LOG_NEW, 0, 0, 0);
  2478.     using_update_log=1;
  2479.   }
  2480.   if (opt_slow_log)
  2481.     open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
  2482.        NullS, LOG_NORMAL, 0, 0, 0);
  2483.   if (opt_bin_log)
  2484.   {
  2485.     /* If we fail to open binlog, it's going to hinder our recovery, so die */
  2486.     if (open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
  2487.  opt_binlog_index_name, LOG_BIN, 0, 0, max_binlog_size))
  2488.       unireg_abort(1);
  2489.     using_update_log=1;
  2490. #ifdef HAVE_REPLICATION
  2491.     if (expire_logs_days)
  2492.     {
  2493.       long purge_time= time(0) - expire_logs_days*24*60*60;
  2494.       if (purge_time >= 0)
  2495. mysql_bin_log.purge_logs_before_date(purge_time);
  2496.     }
  2497. #endif
  2498.   }
  2499.   else if (opt_log_slave_updates)
  2500.   {
  2501.       sql_print_warning("
  2502. you need to use --log-bin to make --log-slave-updates work. 
  2503. Now disabling --log-slave-updates.");
  2504.   }
  2505. #ifdef HAVE_REPLICATION
  2506.   if (opt_log_slave_updates && replicate_same_server_id)
  2507.   {
  2508.     sql_print_error("
  2509. using --replicate-same-server-id in conjunction with 
  2510. --log-slave-updates is impossible, it would lead to infinite loops in this 
  2511. server.");
  2512.     unireg_abort(1);
  2513.   }
  2514. #endif
  2515.   if (opt_error_log)
  2516.   {
  2517.     if (!log_error_file_ptr[0])
  2518.       fn_format(log_error_file, glob_hostname, mysql_data_home, ".err",
  2519.                 MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
  2520.     else
  2521.       fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
  2522. MY_UNPACK_FILENAME | MY_SAFE_PATH);
  2523.     if (!log_error_file[0])
  2524.       opt_error_log= 1; // Too long file name
  2525.     else
  2526.     {
  2527. #ifndef EMBEDDED_LIBRARY
  2528.       if (freopen(log_error_file, "a+", stdout))
  2529. #endif
  2530. stderror_file= freopen(log_error_file, "a+", stderr);
  2531.     }
  2532.   }
  2533.   if (opt_innodb_safe_binlog)
  2534.   {
  2535.     if (have_innodb != SHOW_OPTION_YES)
  2536.       sql_print_warning("--innodb-safe-binlog is meaningful only if "
  2537.                       "the InnoDB storage engine is enabled in the server.");
  2538. #ifdef HAVE_INNOBASE_DB
  2539.     if (innobase_flush_log_at_trx_commit != 1)
  2540.     {
  2541.       sql_print_warning("--innodb-safe-binlog is meaningful only if "
  2542.                       "innodb_flush_log_at_trx_commit is 1; now setting it "
  2543.                       "to 1.");
  2544.       innobase_flush_log_at_trx_commit= 1;
  2545.     }
  2546.     if (innobase_unix_file_flush_method)
  2547.     {
  2548.       /*
  2549.         This option has so many values that it's hard to know which value is
  2550.         good (especially "littlesync", and on Windows... see
  2551.         srv/srv0start.c).
  2552.       */
  2553.       sql_print_warning("--innodb-safe-binlog requires that "
  2554.                       "the innodb_flush_method actually synchronizes the "
  2555.                       "InnoDB log to disk; it is your responsibility "
  2556.                       "to verify that the method you chose does it.");
  2557.     }
  2558.     if (sync_binlog_period != 1)
  2559.     {
  2560.       sql_print_warning("--innodb-safe-binlog is meaningful only if "
  2561.                       "the global sync_binlog variable is 1; now setting it "
  2562.                       "to 1.");
  2563.       sync_binlog_period= 1;
  2564.     }
  2565. #endif
  2566.   }
  2567.   if (ha_init())
  2568.   {
  2569.     sql_print_error("Can't init databases");
  2570.     unireg_abort(1);
  2571.   }
  2572.   if (opt_myisam_log)
  2573.     (void) mi_log(1);
  2574.   /*
  2575.     Now that InnoDB is initialized, we can know the last good binlog position
  2576.     and cut the binlog if needed. This function does nothing if there was no
  2577.     crash recovery by InnoDB.
  2578.   */
  2579.   if (opt_innodb_safe_binlog)
  2580.   {
  2581.     /* not fatal if fails (but print errors) */
  2582.     mysql_bin_log.cut_spurious_tail();
  2583.   }
  2584.   mysql_bin_log.report_pos_in_innodb();
  2585.   /* call ha_init_key_cache() on all key caches to init them */
  2586.   process_key_caches(&ha_init_key_cache);
  2587. #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
  2588.   if (locked_in_memory && !getuid())
  2589.   {
  2590.     if (setreuid((uid_t)-1, 0) == -1)
  2591.     {                        // this should never happen
  2592.       sql_perror("setreuid");
  2593.       unireg_abort(1);
  2594.     }
  2595.     if (mlockall(MCL_CURRENT))
  2596.     {
  2597.       if (global_system_variables.log_warnings)
  2598. sql_print_warning("Failed to lock memory. Errno: %dn",errno);
  2599.       locked_in_memory= 0;
  2600.     }
  2601.     if (user_info)
  2602.       set_user(mysqld_user, user_info);
  2603.   }
  2604.   else
  2605. #endif
  2606.     locked_in_memory=0;
  2607.   ft_init_stopwords();
  2608.   init_max_user_conn();
  2609.   init_update_queries();
  2610.   DBUG_RETURN(0);
  2611. }
  2612. static void create_maintenance_thread()
  2613. {
  2614.   if (
  2615. #ifdef HAVE_BERKELEY_DB
  2616.       (have_berkeley_db == SHOW_OPTION_YES) ||
  2617. #endif
  2618.       (flush_time && flush_time != ~(ulong) 0L))
  2619.   {
  2620.     pthread_t hThread;
  2621.     if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
  2622.       sql_print_warning("Can't create thread to manage maintenance");
  2623.   }
  2624. }
  2625. static void create_shutdown_thread()
  2626. {
  2627. #if !defined(EMBEDDED_LIBRARY)
  2628. #ifdef __WIN__
  2629.   hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
  2630.   pthread_t hThread;
  2631.   if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
  2632.     sql_print_warning("Can't create thread to handle shutdown requests");
  2633.   // On "Stop Service" we have to do regular shutdown
  2634.   Service.SetShutdownEvent(hEventShutdown);
  2635. #endif
  2636. #ifdef OS2
  2637.   pthread_cond_init(&eventShutdown, NULL);
  2638.   pthread_t hThread;
  2639.   if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
  2640.     sql_print_warning("Can't create thread to handle shutdown requests");
  2641. #endif
  2642. #endif // EMBEDDED_LIBRARY 
  2643. }
  2644. #if defined(__NT__) || defined(HAVE_SMEM)
  2645. static void handle_connections_methods()
  2646. {
  2647.   pthread_t hThread;
  2648.   DBUG_ENTER("handle_connections_methods");
  2649. #ifdef __NT__
  2650.   if (hPipe == INVALID_HANDLE_VALUE &&
  2651.       (!have_tcpip || opt_disable_networking) &&
  2652.       !opt_enable_shared_memory)
  2653.   {
  2654.     sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
  2655.     unireg_abort(1); // Will not return
  2656.   }
  2657. #endif
  2658.   pthread_mutex_lock(&LOCK_thread_count);
  2659.   (void) pthread_cond_init(&COND_handler_count,NULL);
  2660.   handler_count=0;
  2661. #ifdef __NT__
  2662.   if (hPipe != INVALID_HANDLE_VALUE)
  2663.   {
  2664.     handler_count++;
  2665.     if (pthread_create(&hThread,&connection_attrib,
  2666.        handle_connections_namedpipes, 0))
  2667.     {
  2668.       sql_print_warning("Can't create thread to handle named pipes");
  2669.       handler_count--;
  2670.     }
  2671.   }
  2672. #endif /* __NT__ */
  2673.   if (have_tcpip && !opt_disable_networking)
  2674.   {
  2675.     handler_count++;
  2676.     if (pthread_create(&hThread,&connection_attrib,
  2677.        handle_connections_sockets, 0))
  2678.     {
  2679.       sql_print_warning("Can't create thread to handle TCP/IP");
  2680.       handler_count--;
  2681.     }
  2682.   }
  2683. #ifdef HAVE_SMEM
  2684.   if (opt_enable_shared_memory)
  2685.   {
  2686.     handler_count++;
  2687.     if (pthread_create(&hThread,&connection_attrib,
  2688.        handle_connections_shared_memory, 0))
  2689.     {
  2690.       sql_print_warning("Can't create thread to handle shared memory");
  2691.       handler_count--;
  2692.     }
  2693.   }
  2694. #endif 
  2695.   while (handler_count > 0)
  2696.     pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
  2697.   pthread_mutex_unlock(&LOCK_thread_count);
  2698.   DBUG_VOID_RETURN;
  2699. }
  2700. void decrement_handler_count()
  2701. {
  2702.   pthread_mutex_lock(&LOCK_thread_count);
  2703.   handler_count--;
  2704.   pthread_mutex_unlock(&LOCK_thread_count);
  2705.   pthread_cond_signal(&COND_handler_count);
  2706. }
  2707. #else
  2708. #define decrement_handler_count()
  2709. #endif /* defined(__NT__) || defined(HAVE_SMEM) */
  2710. #ifndef EMBEDDED_LIBRARY
  2711. #ifdef __WIN__
  2712. int win_main(int argc, char **argv)
  2713. #else
  2714. int main(int argc, char **argv)
  2715. #endif
  2716. {
  2717.   DEBUGGER_OFF;
  2718.   MY_INIT(argv[0]); // init my_sys library & pthreads
  2719. #ifdef _CUSTOMSTARTUPCONFIG_
  2720.   if (_cust_check_startup())
  2721.   {
  2722.     / * _cust_check_startup will report startup failure error * /
  2723.     exit( 1 );
  2724.   }
  2725. #endif
  2726.   if (init_common_variables(MYSQL_CONFIG_NAME,
  2727.     argc, argv, load_default_groups))
  2728.     unireg_abort(1); // Will do exit
  2729.   init_signals();
  2730.   if (!(opt_specialflag & SPECIAL_NO_PRIOR))
  2731.     my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
  2732.   pthread_attr_setstacksize(&connection_attrib,thread_stack);
  2733. #ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
  2734.   {
  2735.     /* Retrieve used stack size;  Needed for checking stack overflows */
  2736.     size_t stack_size= 0;
  2737.     pthread_attr_getstacksize(&connection_attrib, &stack_size);
  2738.     /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
  2739.     if (stack_size && stack_size < thread_stack)
  2740.     {
  2741.       if (global_system_variables.log_warnings)
  2742. sql_print_warning("Asked for %ld thread stack, but got %ld",
  2743. thread_stack, stack_size);
  2744.       thread_stack= stack_size;
  2745.     }
  2746.   }
  2747. #endif
  2748.   thread_stack_min=thread_stack - STACK_MIN_SIZE;
  2749.   (void) thr_setconcurrency(concurrency); // 10 by default
  2750.   select_thread=pthread_self();
  2751.   select_thread_in_use=1;
  2752.   init_ssl();
  2753. #ifdef HAVE_LIBWRAP
  2754.   libwrapName= my_progname+dirname_length(my_progname);
  2755.   openlog(libwrapName, LOG_PID, LOG_AUTH);
  2756. #endif
  2757.   /*
  2758.     We have enough space for fiddling with the argv, continue
  2759.   */
  2760.   check_data_home(mysql_real_data_home);
  2761.   if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
  2762.   {
  2763.     unireg_abort(1); /* purecov: inspected */
  2764.   }
  2765.   mysql_data_home= mysql_data_home_buff;
  2766.   mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
  2767.   mysql_data_home[1]=0;
  2768.   server_init();
  2769.   if (opt_bin_log && !server_id)
  2770.   {
  2771.     server_id= !master_host ? 1 : 2;
  2772. #ifdef EXTRA_DEBUG
  2773.     switch (server_id) {
  2774.     case 1:
  2775.       sql_print_warning("
  2776. You have enabled the binary log, but you haven't set server-id to 
  2777. a non-zero value: we force server id to 1; updates will be logged to the 
  2778. binary log, but connections from slaves will not be accepted.");
  2779.       break;
  2780.     case 2:
  2781.       sql_print_warning("
  2782. You should set server-id to a non-0 value if master_host is set; 
  2783. we force server id to 2, but this MySQL server will not act as a slave.");
  2784.       break;
  2785.     }
  2786. #endif
  2787.   }
  2788.   if (init_server_components())
  2789.     exit(1);
  2790. #ifdef __WIN__
  2791.   if (!opt_console)
  2792.   {
  2793.     freopen(log_error_file,"a+",stdout);
  2794.     freopen(log_error_file,"a+",stderr);
  2795.     FreeConsole(); // Remove window
  2796.   }
  2797. #endif
  2798.   /*
  2799.     init signals & alarm
  2800.     After this we can't quit by a simple unireg_abort
  2801.   */
  2802.   error_handler_hook = my_message_sql;
  2803.   start_signal_handler(); // Creates pidfile
  2804.   if (acl_init(opt_noacl) ||
  2805.       my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
  2806.   {
  2807.     abort_loop=1;
  2808.     select_thread_in_use=0;
  2809. #ifndef __NETWARE__
  2810.     (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
  2811. #endif /* __NETWARE__ */
  2812.     
  2813.     if (!opt_bootstrap)
  2814.       (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
  2815.     if (unix_sock != INVALID_SOCKET)
  2816.       unlink(mysqld_unix_port);
  2817.     exit(1);
  2818.   }
  2819.   if (!opt_noacl)
  2820.     (void) grant_init();
  2821. #ifdef HAVE_DLOPEN
  2822.   if (!opt_noacl)
  2823.     udf_init();
  2824. #endif
  2825.   if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
  2826.     opt_skip_slave_start= 1;
  2827.   /*
  2828.     init_slave() must be called after the thread keys are created.
  2829.     Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
  2830.     places) assume that active_mi != 0, so let's fail if it's 0 (out of
  2831.     memory); a message has already been printed.
  2832.   */
  2833.   if (init_slave() && !active_mi)
  2834.   {
  2835.     end_thr_alarm(1); // Don't allow alarms
  2836.     unireg_abort(1);
  2837.   }
  2838.   if (opt_bootstrap)
  2839.   {
  2840.     select_thread_in_use= 0;                    // Allow 'kill' to work
  2841.     int error= bootstrap(stdin);
  2842.     end_thr_alarm(1); // Don't allow alarms
  2843.     unireg_abort(error ? 1 : 0);
  2844.   }
  2845.   if (opt_init_file)
  2846.   {
  2847.     if (read_init_file(opt_init_file))
  2848.     {
  2849.       end_thr_alarm(1); // Don't allow alarms
  2850.       unireg_abort(1);
  2851.     }
  2852.   }
  2853.   create_shutdown_thread();
  2854.   create_maintenance_thread();
  2855.   printf(ER(ER_READY),my_progname,server_version,
  2856.  ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port),
  2857.  mysqld_port, "");
  2858.   if (MYSQL_COMPILATION_COMMENT[0] != '')
  2859.     fputs("  " MYSQL_COMPILATION_COMMENT, stdout);
  2860.   putchar('n');
  2861.   fflush(stdout);
  2862. #if defined(__NT__) || defined(HAVE_SMEM)
  2863.   handle_connections_methods();
  2864. #else
  2865. #ifdef __WIN__
  2866.   if ( !have_tcpip || opt_disable_networking)
  2867.   {
  2868.     sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
  2869.     unireg_abort(1);
  2870.   }
  2871. #endif
  2872.   handle_connections_sockets(0);
  2873. #endif /* __NT__ */
  2874.   /* (void) pthread_attr_destroy(&connection_attrib); */
  2875.   
  2876.   DBUG_PRINT("quit",("Exiting main thread"));
  2877. #ifndef __WIN__
  2878. #ifdef EXTRA_DEBUG2
  2879.   sql_print_error("Before Lock_thread_count");
  2880. #endif
  2881.   (void) pthread_mutex_lock(&LOCK_thread_count);
  2882.   DBUG_PRINT("quit", ("Got thread_count mutex"));
  2883.   select_thread_in_use=0; // For close_connections
  2884.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  2885.   (void) pthread_cond_broadcast(&COND_thread_count);
  2886. #ifdef EXTRA_DEBUG2
  2887.   sql_print_error("After lock_thread_count");
  2888. #endif
  2889. #endif /* __WIN__ */
  2890.   /* Wait until cleanup is done */
  2891.   (void) pthread_mutex_lock(&LOCK_thread_count);
  2892.   while (!ready_to_exit)
  2893.     pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
  2894.   (void) pthread_mutex_unlock(&LOCK_thread_count);
  2895. #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
  2896.   if (Service.IsNT() && start_mode)
  2897.     Service.Stop();
  2898.   else
  2899.   {
  2900.     Service.SetShutdownEvent(0);
  2901.     if (hEventShutdown)
  2902.       CloseHandle(hEventShutdown);
  2903.   }
  2904. #endif
  2905.   wait_for_signal_thread_to_end();
  2906.   clean_up_mutexes();
  2907.   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
  2908.  
  2909.   exit(0);
  2910.   return(0); /* purecov: deadcode */
  2911. }
  2912. #endif /* EMBEDDED_LIBRARY */
  2913. /****************************************************************************
  2914.   Main and thread entry function for Win32
  2915.   (all this is needed only to run mysqld as a service on WinNT)
  2916. ****************************************************************************/
  2917. #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
  2918. int mysql_service(void *p)
  2919. {
  2920.   if (use_opt_args)
  2921.     win_main(opt_argc, opt_argv);
  2922.   else
  2923.     win_main(Service.my_argc, Service.my_argv);
  2924.   return 0;
  2925. }
  2926. /* Quote string if it contains space, else copy */
  2927. static char *add_quoted_string(char *to, const char *from, char *to_end)
  2928. {
  2929.   uint length= (uint) (to_end-to);
  2930.   if (!strchr(from, ' '))
  2931.     return strnmov(to, from, length);
  2932.   return strxnmov(to, length, """, from, """, NullS);
  2933. }
  2934. /*
  2935.   Handle basic handling of services, like installation and removal
  2936.   SYNOPSIS
  2937.     default_service_handling()
  2938.     argv Pointer to argument list
  2939.     servicename Internal name of service
  2940.     displayname Display name of service (in taskbar ?)
  2941.     file_path Path to this program
  2942.     startup_option Startup option to mysqld
  2943.   RETURN VALUES
  2944.     0 option handled
  2945.     1 Could not handle option
  2946.  */
  2947. static bool
  2948. default_service_handling(char **argv,
  2949.  const char *servicename,
  2950.  const char *displayname,
  2951.  const char *file_path,
  2952.  const char *extra_opt)
  2953. {
  2954.   char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
  2955.   end= path_and_service + sizeof(path_and_service)-3;
  2956.   /* We have to quote filename if it contains spaces */
  2957.   pos= add_quoted_string(path_and_service, file_path, end);
  2958.   if (*extra_opt)
  2959.   {
  2960.     /* Add (possible quoted) option after file_path */
  2961.     *pos++= ' ';
  2962.     pos= add_quoted_string(pos, extra_opt, end);
  2963.   }
  2964.   /* We must have servicename last */
  2965.   *pos++= ' ';
  2966.   (void) add_quoted_string(pos, servicename, end);
  2967.   if (Service.got_service_option(argv, "install"))
  2968.   {
  2969.     Service.Install(1, servicename, displayname, path_and_service);
  2970.     return 0;
  2971.   }
  2972.   if (Service.got_service_option(argv, "install-manual"))
  2973.   {
  2974.     Service.Install(0, servicename, displayname, path_and_service);
  2975.     return 0;
  2976.   }
  2977.   if (Service.got_service_option(argv, "remove"))
  2978.   {
  2979.     Service.Remove(servicename);
  2980.     return 0;
  2981.   }
  2982.   return 1;
  2983. }
  2984. int main(int argc, char **argv)
  2985. {
  2986.   /* When several instances are running on the same machine, we
  2987.      need to have an  unique  named  hEventShudown  through the
  2988.      application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
  2989.   */ 
  2990.   int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
  2991.           "MySQLShutdown"), 10);
  2992.   
  2993.   /* Must be initialized early for comparison of service name */
  2994.   system_charset_info= &my_charset_utf8_general_ci;
  2995.   if (Service.GetOS()) /* true NT family */
  2996.   {
  2997.     char file_path[FN_REFLEN];
  2998.     my_path(file_path, argv[0], "");       /* Find name in path */
  2999.     fn_format(file_path,argv[0],file_path,"",
  3000.       MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
  3001.     if (argc == 2)
  3002.     {
  3003.       if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
  3004.    file_path, ""))
  3005. return 0;
  3006.       if (Service.IsService(argv[1]))        /* Start an optional service */
  3007.       {
  3008. /*
  3009.   Only add the service name to the groups read from the config file
  3010.   if it's not "MySQL". (The default service name should be 'mysqld'
  3011.   but we started a bad tradition by calling it MySQL from the start
  3012.   and we are now stuck with it.
  3013. */
  3014. if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
  3015.   load_default_groups[load_default_groups_sz-2]= argv[1];
  3016.         start_mode= 1;
  3017.         Service.Init(argv[1], mysql_service);
  3018.         return 0;
  3019.       }
  3020.     }
  3021.     else if (argc == 3) /* install or remove any optional service */
  3022.     {
  3023.       if (!default_service_handling(argv, argv[2], argv[2], file_path, ""))
  3024. return 0;
  3025.       if (Service.IsService(argv[2]))
  3026.       {
  3027. /*
  3028.   mysqld was started as
  3029.   mysqld --defaults-file=my_pathmy.ini service-name
  3030. */
  3031. use_opt_args=1;
  3032. opt_argc= 2; // Skip service-name
  3033. opt_argv=argv;
  3034. start_mode= 1;
  3035. if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
  3036.   load_default_groups[load_default_groups_sz-2]= argv[2];
  3037. Service.Init(argv[2], mysql_service);
  3038. return 0;
  3039.       }
  3040.     }
  3041.     else if (argc == 4)
  3042.     {
  3043.       /*
  3044. Install an optional service with optional config file
  3045. mysqld --install-manual mysqldopt --defaults-file=c:miguelmy.ini
  3046.       */
  3047.       if (!default_service_handling(argv, argv[2], argv[2], file_path,
  3048.     argv[3]))
  3049. return 0;
  3050.     }
  3051.     else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
  3052.     {
  3053.       /* start the default service */
  3054.       start_mode= 1;
  3055.       Service.Init(MYSQL_SERVICENAME, mysql_service);
  3056.       return 0;
  3057.     }
  3058.   }
  3059.   /* Start as standalone server */
  3060.   Service.my_argc=argc;
  3061.   Service.my_argv=argv;
  3062.   mysql_service(NULL);
  3063.   return 0;
  3064. }
  3065. #endif
  3066. /*
  3067.   Execute all commands from a file. Used by the mysql_install_db script to
  3068.   create MySQL privilege tables without having to start a full MySQL server.
  3069. */
  3070. static int bootstrap(FILE *file)
  3071. {
  3072.   int error= 0;
  3073.   DBUG_ENTER("bootstrap");
  3074.   THD *thd= new THD;
  3075.   thd->bootstrap=1;
  3076.   my_net_init(&thd->net,(st_vio*) 0);
  3077.   thd->max_client_packet_length= thd->net.max_packet;
  3078.   thd->master_access= ~(ulong)0;
  3079.   thd->thread_id=thread_id++;
  3080.   thread_count++;