mysqld.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:130k
- /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- #include "mysql_priv.h"
- #include <mysql.h>
- #include <m_ctype.h>
- #include "sql_acl.h"
- #include "slave.h"
- #ifdef HAVE_BERKELEY_DB
- #include "ha_berkeley.h"
- #endif
- #ifdef HAVE_INNOBASE_DB
- #include "ha_innobase.h"
- #endif
- #include "ha_myisam.h"
- #include <nisam.h>
- #include <thr_alarm.h>
- #include <ft_global.h>
- #ifndef DBUG_OFF
- #define ONE_THREAD
- #endif
- extern "C" { // Because of SCO 3.2V4.2
- #include <errno.h>
- #include <sys/stat.h>
- #ifndef __GNU_LIBRARY__
- #define __GNU_LIBRARY__ // Skip warnings in getopt.h
- #endif
- #include <getopt.h>
- #ifdef HAVE_SYSENT_H
- #include <sysent.h>
- #endif
- #ifdef HAVE_PWD_H
- #include <pwd.h> // For getpwent
- #endif
- #ifdef HAVE_GRP_H
- #include <grp.h>
- #endif
- #ifndef __WIN__
- #include <sys/resource.h>
- #ifdef HAVE_SYS_UN_H
- # include <sys/un.h>
- #endif
- #include <netdb.h>
- #ifdef HAVE_SELECT_H
- # include <select.h>
- #endif
- #ifdef HAVE_SYS_SELECT_H
- #include <sys/select.h>
- #endif
- #include <sys/utsname.h>
- #else
- #include <windows.h>
- #endif // __WIN__
- #ifdef HAVE_LIBWRAP
- #include <tcpd.h>
- #include <syslog.h>
- #ifdef NEED_SYS_SYSLOG_H
- #include <sys/syslog.h>
- #endif /* NEED_SYS_SYSLOG_H */
- int allow_severity = LOG_INFO;
- int deny_severity = LOG_WARNING;
- #endif /* HAVE_LIBWRAP */
- #ifdef HAVE_SYS_MMAN_H
- #include <sys/mman.h>
- #endif
- #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
- #include <ieeefp.h>
- #ifdef HAVE_FP_EXCEPT // Fix type conflict
- typedef fp_except fp_except_t;
- #endif
- /* We can't handle floating point expections with threads, so disable
- this on freebsd
- */
- inline void reset_floating_point_exceptions()
- {
- /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
- fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL |
- FP_X_DZ | FP_X_IMP));
- }
- #else
- #define reset_floating_point_exceptions()
- #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
- } /* cplusplus */
- #if defined(HAVE_LINUXTHREADS)
- #define THR_KILL_SIGNAL SIGINT
- #else
- #define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads
- #endif
- #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
- #include <sys/types.h>
- #else
- #include <my_pthread.h> // For thr_setconcurency()
- #endif
- #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) && !defined(HAVE_mit_thread)
- #define SET_RLIMIT_NOFILE
- #endif
- #ifdef SOLARIS
- extern "C" int gethostname(char *name, int namelen);
- #endif
- #define MYSQL_KILL_SIGNAL SIGTERM
- #ifndef DBUG_OFF
- static const char* default_dbug_option=IF_WIN("d:t:i:O,\mysqld.trace",
- "d:t:i:o,/tmp/mysqld.trace");
- #endif
- #ifdef __NT__
- static char szPipeName [ 257 ];
- static SECURITY_ATTRIBUTES saPipeSecurity;
- static SECURITY_DESCRIPTOR sdPipeDescriptor;
- static HANDLE hPipe = INVALID_HANDLE_VALUE;
- static pthread_cond_t COND_handler_count;
- static uint handler_count;
- #endif
- #ifdef __WIN__
- static bool opt_console=0;
- #endif
- #ifdef HAVE_BERKELEY_DB
- SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES;
- #else
- SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_NO;
- #endif
- #ifdef HAVE_GEMINI_DB
- SHOW_COMP_OPTION have_gemini=SHOW_OPTION_YES;
- #else
- SHOW_COMP_OPTION have_gemini=SHOW_OPTION_NO;
- #endif
- #ifdef HAVE_INNOBASE_DB
- SHOW_COMP_OPTION have_innobase=SHOW_OPTION_YES;
- #else
- SHOW_COMP_OPTION have_innobase=SHOW_OPTION_NO;
- #endif
- #ifndef NO_ISAM
- SHOW_COMP_OPTION have_isam=SHOW_OPTION_YES;
- #else
- SHOW_COMP_OPTION have_isam=SHOW_OPTION_NO;
- #endif
- #ifdef USE_RAID
- SHOW_COMP_OPTION have_raid=SHOW_OPTION_YES;
- #else
- SHOW_COMP_OPTION have_raid=SHOW_OPTION_NO;
- #endif
- #ifdef HAVE_OPENSSL
- SHOW_COMP_OPTION have_ssl=SHOW_OPTION_YES;
- #else
- SHOW_COMP_OPTION have_ssl=SHOW_OPTION_NO;
- #endif
- static bool opt_skip_slave_start = 0; // if set, slave is not autostarted
- static ulong opt_specialflag=SPECIAL_ENGLISH;
- static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
- static ulong back_log,connect_timeout,concurrency;
- static my_string opt_logname=0,opt_update_logname=0,
- opt_binlog_index_name = 0,opt_slow_logname=0;
- static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN];
- static pthread_t select_thread;
- static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl,
- opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0,
- opt_ansi_mode=0,opt_myisam_log=0,
- opt_large_files=sizeof(my_off_t) > 4;
- bool opt_sql_bin_update = 0, opt_log_slave_updates = 0, opt_safe_show_db=0;
- FILE *bootstrap_file=0;
- int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
- extern MASTER_INFO glob_mi;
- extern int init_master_info(MASTER_INFO* mi);
- // if sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync,
- // and are treated as aliases for each other
- static bool kill_in_progress=FALSE;
- static struct rand_struct sql_rand;
- static int cleanup_done;
- static char **defaults_argv,time_zone[30];
- static const char *default_table_type_name;
- static char glob_hostname[FN_REFLEN];
- #ifdef HAVE_OPENSSL
- static bool opt_use_ssl = FALSE;
- static char *opt_ssl_key = 0;
- static char *opt_ssl_cert = 0;
- static char *opt_ssl_ca = 0;
- static char *opt_ssl_capath = 0;
- static VioSSLAcceptorFd* ssl_acceptor_fd = 0;
- #endif /* HAVE_OPENSSL */
- I_List <i_string_pair> replicate_rewrite_db;
- I_List<i_string> replicate_do_db, replicate_ignore_db;
- // allow the user to tell us which db to replicate and which to ignore
- I_List<i_string> binlog_do_db, binlog_ignore_db;
- /* if we guessed server_id , we need to know about it */
- uint32 server_id = 0;
- bool server_id_supplied = 0;
- uint mysql_port;
- uint test_flags, select_errors=0, dropping_tables=0,ha_open_options=0;
- uint volatile thread_count=0, thread_running=0, kill_cached_threads=0,
- wake_thread=0, global_read_lock=0;
- ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
- OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE );
- uint protocol_version=PROTOCOL_VERSION;
- ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
- max_join_size,join_buff_size,tmp_table_size,thread_stack,
- thread_stack_min,net_wait_timeout,what_to_log= ~ (1L << (uint) COM_TIME),
- query_buff_size, lower_case_table_names, mysqld_net_retry_count,
- net_interactive_timeout, slow_launch_time = 2L,
- net_read_timeout,net_write_timeout,slave_open_temp_tables=0,
- open_files_limit=0, max_binlog_size;
- ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
- volatile ulong cached_thread_count=0;
- // replication parameters, if master_host is not NULL, we are a slave
- my_string master_user = (char*) "test", master_password = 0, master_host=0,
- master_info_file = (char*) "master.info";
- const char *localhost=LOCAL_HOST;
- const char *delayed_user="DELAYED";
- uint master_port = MYSQL_PORT, master_connect_retry = 60;
- ulong max_tmp_tables,max_heap_table_size;
- ulong bytes_sent = 0L, bytes_received = 0L;
- bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory;
- bool opt_using_transactions;
- bool volatile abort_loop,select_thread_in_use,grant_option;
- bool volatile ready_to_exit,shutdown_in_progress;
- ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
- ulong query_id=1L,long_query_count,long_query_time,aborted_threads,
- aborted_connects,delayed_insert_timeout,delayed_insert_limit,
- delayed_queue_size,delayed_insert_threads,delayed_insert_writes,
- delayed_rows_in_use,delayed_insert_errors,flush_time, thread_created;
- ulong filesort_rows, filesort_range_count, filesort_scan_count;
- ulong filesort_merge_passes;
- ulong select_range_check_count, select_range_count, select_scan_count;
- ulong select_full_range_join_count,select_full_join_count;
- ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
- created_tmp_disk_tables=0;
- ulong max_connections,max_insert_delayed_threads,max_used_connections,
- max_connect_errors, max_user_connections = 0;
- ulong thread_id=1L,current_pid;
- ulong slow_launch_threads = 0;
- char mysql_real_data_home[FN_REFLEN],
- mysql_data_home[2],language[LIBLEN],reg_ext[FN_EXTLEN],
- default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
- blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
- *opt_init_file;
- char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
- char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
- const char *first_keyword="first";
- const char **errmesg; /* Error messages */
- const char *myisam_recover_options_str="OFF";
- my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
- ulong my_bind_addr; /* the address we bind to */
- DATE_FORMAT dayord;
- double log_10[32]; /* 10 potences */
- I_List<THD> threads,thread_cache;
- time_t start_time;
- MY_BITMAP temp_pool;
- bool use_temp_pool=0;
- pthread_key(MEM_ROOT*,THR_MALLOC);
- pthread_key(THD*, THR_THD);
- pthread_key(NET*, THR_NET);
- pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
- LOCK_mapped_file, LOCK_status, LOCK_grant,
- LOCK_error_log,
- LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
- LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
- LOCK_binlog_update, LOCK_slave, LOCK_server_id,
- LOCK_user_conn;
- pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update,
- COND_slave_stopped, COND_slave_start;
- pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
- pthread_t signal_thread;
- pthread_attr_t connection_attrib;
- enum db_type default_table_type=DB_TYPE_MYISAM;
- #ifdef __WIN__
- #undef getpid
- #include <process.h>
- HANDLE hEventShutdown;
- #include "nt_servc.h"
- static NTService Service; // Service object for WinNT
- #endif
- static void *signal_hand(void *arg);
- static void set_options(void);
- static void get_options(int argc,char **argv);
- static char *get_relative_path(const char *path);
- static void fix_paths(void);
- static pthread_handler_decl(handle_connections_sockets,arg);
- static int bootstrap(FILE *file);
- static bool read_init_file(char *file_name);
- #ifdef __NT__
- static pthread_handler_decl(handle_connections_namedpipes,arg);
- #endif
- #ifdef __WIN__
- static int get_service_parameters();
- #endif
- extern pthread_handler_decl(handle_slave,arg);
- #ifdef SET_RLIMIT_NOFILE
- static uint set_maximum_open_files(uint max_file_limit);
- #endif
- static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
- /****************************************************************************
- ** Code to end mysqld
- ****************************************************************************/
- static void close_connections(void)
- {
- #ifdef EXTRA_DEBUG
- int count=0;
- #endif
- NET net;
- DBUG_ENTER("close_connections");
- /* Clear thread cache */
- kill_cached_threads++;
- flush_thread_cache();
- /* kill flush thread */
- (void) pthread_mutex_lock(&LOCK_manager);
- if (manager_thread_in_use)
- {
- DBUG_PRINT("quit",("killing manager thread: %lx",manager_thread));
- (void) pthread_cond_signal(&COND_manager);
- }
- (void) pthread_mutex_unlock(&LOCK_manager);
- /* kill connection thread */
- #if !defined(__WIN__) && !defined(__EMX__)
- DBUG_PRINT("quit",("waiting for select thread: %lx",select_thread));
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (select_thread_in_use)
- {
- struct timespec abstime;
- int error;
- LINT_INIT(error);
- #ifndef DONT_USE_THR_ALARM
- if (pthread_kill(select_thread,THR_CLIENT_ALARM))
- break; // allready dead
- #endif
- #ifdef HAVE_TIMESPEC_TS_SEC
- abstime.ts_sec=time(NULL)+2; // Bsd 2.1
- abstime.ts_nsec=0;
- #else
- struct timeval tv;
- gettimeofday(&tv,0);
- abstime.tv_sec=tv.tv_sec+2;
- abstime.tv_nsec=tv.tv_usec*1000;
- #endif
- for (uint tmp=0 ; tmp < 10 ; tmp++)
- {
- error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
- &abstime);
- if (error != EINTR)
- break;
- }
- #ifdef EXTRA_DEBUG
- if (error != 0 && !count++)
- sql_print_error("Got error %d from pthread_cond_timedwait",error);
- #endif
- #if defined(AIX_3_2) || defined(HAVE_DEC_3_2_THREADS)
- if (ip_sock != INVALID_SOCKET)
- {
- DBUG_PRINT("error",("closing TCP/IP and socket files"));
- VOID(shutdown(ip_sock,2));
- VOID(closesocket(ip_sock));
- VOID(shutdown(unix_sock,2));
- VOID(closesocket(unix_sock));
- VOID(unlink(mysql_unix_port));
- ip_sock=unix_sock= INVALID_SOCKET;
- }
- #endif
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- #endif /* __WIN__ */
- /* Abort listening to new connections */
- DBUG_PRINT("quit",("Closing sockets"));
- if ( !opt_disable_networking )
- {
- if (ip_sock != INVALID_SOCKET)
- {
- (void) shutdown(ip_sock,2);
- (void) closesocket(ip_sock);
- ip_sock= INVALID_SOCKET;
- }
- }
- #ifdef __NT__
- if ( hPipe != INVALID_HANDLE_VALUE )
- {
- HANDLE hTempPipe = hPipe;
- DBUG_PRINT( "quit", ("Closing named pipes") );
- hPipe = INVALID_HANDLE_VALUE;
- CancelIo( hTempPipe );
- DisconnectNamedPipe( hTempPipe );
- CloseHandle( hTempPipe );
- }
- #endif
- #ifdef HAVE_SYS_UN_H
- if (unix_sock != INVALID_SOCKET)
- {
- (void) shutdown(unix_sock,2);
- (void) closesocket(unix_sock);
- (void) unlink(mysql_unix_port);
- unix_sock= INVALID_SOCKET;
- }
- #endif
- end_thr_alarm(); // Don't allow alarms
- /* First signal all threads that it's time to die */
- THD *tmp;
- (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
- I_List_iterator<THD> it(threads);
- while ((tmp=it++))
- {
- DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
- tmp->thread_id));
- tmp->killed=1;
- if (tmp->mysys_var)
- {
- tmp->mysys_var->abort=1;
- if (tmp->mysys_var->current_mutex)
- {
- pthread_mutex_lock(tmp->mysys_var->current_mutex);
- pthread_cond_broadcast(tmp->mysys_var->current_cond);
- pthread_mutex_unlock(tmp->mysys_var->current_mutex);
- }
- }
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
- if (thread_count)
- {
- sleep(1); // Give threads time to die
- }
- /* Force remaining threads to die by closing the connection to the client */
- (void) my_net_init(&net, (Vio*) 0);
- for (;;)
- {
- DBUG_PRINT("quit",("Locking LOCK_thread_count"));
- (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
- if (!(tmp=threads.get()))
- {
- DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- break;
- }
- #ifndef __bsdi__ // Bug in BSDI kernel
- if ((net.vio=tmp->net.vio) != 0)
- {
- sql_print_error(ER(ER_FORCING_CLOSE),my_progname,
- tmp->thread_id,tmp->user ? tmp->user : "");
- close_connection(&net,0,0);
- }
- #endif
- DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- }
- net_end(&net);
- /* All threads has now been aborted */
- DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (thread_count)
- {
- (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- mysql_log.close(1);
- mysql_update_log.close(1);
- mysql_bin_log.close(1);
- my_free(charsets_list, MYF(0));
- DBUG_PRINT("quit",("close_connections thread"));
- DBUG_VOID_RETURN;
- }
- void kill_mysql(void)
- {
- DBUG_ENTER("kill_mysql");
- #if defined(__WIN__)
- {
- if (!SetEvent(hEventShutdown))
- {
- DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
- }
- // or:
- // HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
- // SetEvent(hEventShutdown);
- // CloseHandle(hEvent);
- }
- #elif defined(HAVE_PTHREAD_KILL)
- if (pthread_kill(signal_thread,SIGTERM)) /* End everything nicely */
- {
- DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
- }
- #else
- kill(current_pid,SIGTERM);
- #endif
- DBUG_PRINT("quit",("After pthread_kill"));
- shutdown_in_progress=1; // Safety if kill didn't work
- DBUG_VOID_RETURN;
- }
- /* Force server down. kill all connections and threads and exit */
- #ifndef __WIN__
- static void *kill_server(void *sig_ptr)
- #define RETURN_FROM_KILL_SERVER return 0
- #else
- static void __cdecl kill_server(int sig_ptr)
- #define RETURN_FROM_KILL_SERVER return
- #endif
- {
- int sig=(int) (long) sig_ptr; // This is passed a int
- DBUG_ENTER("kill_server");
- // if there is a signal during the kill in progress, we do not need
- // another one
- if (kill_in_progress) // Safety
- RETURN_FROM_KILL_SERVER;
- kill_in_progress=TRUE;
- abort_loop=1; // This should be set
- signal(sig,SIG_IGN);
- if (sig == MYSQL_KILL_SIGNAL || sig == 0)
- sql_print_error(ER(ER_NORMAL_SHUTDOWN),my_progname);
- else
- sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
- #if defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__)
- my_thread_init(); // If this is a new thread
- #endif
- close_connections();
- sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
- if (sig != MYSQL_KILL_SIGNAL && sig != 0)
- unireg_abort(1); /* purecov: inspected */
- else
- unireg_end(0);
- pthread_exit(0); /* purecov: deadcode */
- RETURN_FROM_KILL_SERVER;
- }
- #ifdef USE_ONE_SIGNAL_HAND
- pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
- {
- my_thread_init(); // Initialize new thread
- kill_server(0);
- my_thread_end(); // Normally never reached
- return 0;
- }
- #endif
- static sig_handler print_signal_warning(int sig)
- {
- sql_print_error("Warning: Got signal %d from thread %d",
- sig,my_thread_id());
- #ifdef DONT_REMEMBER_SIGNAL
- sigset(sig,print_signal_warning); /* int. thread system calls */
- #endif
- #ifndef __WIN__
- if (sig == SIGALRM)
- alarm(2); /* reschedule alarm */
- #endif
- }
- void unireg_end(int signal_number __attribute__((unused)))
- {
- clean_up();
- pthread_exit(0); // Exit is in main thread
- }
- void unireg_abort(int exit_code)
- {
- if (exit_code)
- sql_print_error("Abortingn");
- clean_up(); /* purecov: inspected */
- exit(exit_code); /* purecov: inspected */
- }
- void clean_up(void)
- {
- DBUG_PRINT("exit",("clean_up"));
- if (cleanup_done++)
- return; /* purecov: inspected */
- acl_free(1);
- grant_free();
- sql_cache_free();
- table_cache_free();
- hostname_cache_free();
- item_user_lock_free();
- lex_free(); /* Free some memory */
- #ifdef HAVE_DLOPEN
- if (!opt_noacl)
- udf_free();
- #endif
- end_key_cache(); /* This is usually freed automaticly */
- (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
- #ifdef USE_RAID
- end_raid();
- #endif
- x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
- free_defaults(defaults_argv);
- my_free(mysql_tmpdir,MYF(0));
- x_free(opt_bin_logname);
- bitmap_free(&temp_pool);
- free_max_user_conn();
- #ifndef __WIN__
- if (!opt_bootstrap)
- (void) my_delete(pidfile_name,MYF(0)); // This may not always exist
- #endif
- end_slave();
- my_thread_end();
- /* Tell main we are ready */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- ready_to_exit=1;
- /* do the broadcast inside the lock to ensure that my_end() is not called */
- (void) pthread_cond_broadcast(&COND_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- } /* clean_up */
- /****************************************************************************
- ** Init IP and UNIX socket
- ****************************************************************************/
- static void set_ports()
- {
- char *env;
- if (!mysql_port && !opt_disable_networking)
- { // Get port if not from commandline
- struct servent *serv_ptr;
- mysql_port = MYSQL_PORT;
- if ((serv_ptr = getservbyname("mysql", "tcp")))
- mysql_port = ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
- if ((env = getenv("MYSQL_TCP_PORT")))
- mysql_port = (uint) atoi(env); /* purecov: inspected */
- }
- if (!mysql_unix_port)
- {
- #ifdef __WIN__
- mysql_unix_port = (char*) MYSQL_NAMEDPIPE;
- #else
- mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
- #endif
- if ((env = getenv("MYSQL_UNIX_PORT")))
- mysql_unix_port = env; /* purecov: inspected */
- }
- }
- /* Change to run as another user if started with --user */
- static void set_user(const char *user)
- {
- #ifndef __WIN__
- struct passwd *ent;
- // don't bother if we aren't superuser
- if (geteuid())
- {
- if (user)
- fprintf(stderr,
- "Warning: One can only use the --user switch if running as rootn");
- return;
- }
- else if (!user)
- {
- if (!opt_bootstrap)
- {
- fprintf(stderr,"Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root!n");
- unireg_abort(1);
- }
- return;
- }
- if (!strcmp(user,"root"))
- return; // Avoid problem with dynamic libraries
- if (!(ent = getpwnam(user)))
- {
- fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!n",user);
- unireg_abort(1);
- }
- #ifdef HAVE_INITGROUPS
- initgroups((char*) user,ent->pw_gid);
- #endif
- if (setgid(ent->pw_gid) == -1)
- {
- sql_perror("setgid");
- unireg_abort(1);
- }
- if (setuid(ent->pw_uid) == -1)
- {
- sql_perror("setuid");
- unireg_abort(1);
- }
- #endif
- }
- /* Change root user if started with --chroot */
- static void set_root(const char *path)
- {
- #if !defined(__WIN__) && !defined(__EMX__)
- if (chroot(path) == -1)
- {
- sql_perror("chroot");
- unireg_abort(1);
- }
- #endif
- }
- static void server_init(void)
- {
- struct sockaddr_in IPaddr;
- #ifdef HAVE_SYS_UN_H
- struct sockaddr_un UNIXaddr;
- #endif
- int arg=1;
- DBUG_ENTER("server_init");
- #ifdef __WIN__
- if ( !opt_disable_networking )
- {
- WSADATA WsaData;
- if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
- {
- my_message(0,"WSAStartup Failedn",MYF(0));
- unireg_abort(1);
- }
- }
- #endif /* __WIN__ */
- set_ports();
- if (mysql_port != 0 && !opt_disable_networking && !opt_bootstrap)
- {
- DBUG_PRINT("general",("IP Socket is %d",mysql_port));
- ip_sock = socket(AF_INET, SOCK_STREAM, 0);
- if (ip_sock == INVALID_SOCKET)
- {
- DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
- sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */
- unireg_abort(1); /* purecov: tested */
- }
- bzero((char*) &IPaddr, sizeof(IPaddr));
- IPaddr.sin_family = AF_INET;
- IPaddr.sin_addr.s_addr = my_bind_addr;
- IPaddr.sin_port = (unsigned short) htons((unsigned short) mysql_port);
- (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
- for(;;)
- {
- if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr),
- sizeof(IPaddr)) >= 0)
- break;
- DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
- sql_perror("Can't start server: Bind on TCP/IP port");/* Had a loop here */
- sql_print_error("Do you already have another mysqld server running on port: %d ?",mysql_port);
- unireg_abort(1);
- }
- if (listen(ip_sock,(int) back_log) < 0)
- sql_print_error("Warning: listen() on TCP/IP failed with error %d",
- errno);
- }
- if (mysqld_chroot)
- set_root(mysqld_chroot);
- set_user(mysqld_user); // set_user now takes care of mysqld_user==NULL
- #ifdef __NT__
- /* create named pipe */
- if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap)
- {
- sprintf( szPipeName, "\\.\pipe\%s", mysql_unix_port );
- ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) );
- ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) );
- if ( !InitializeSecurityDescriptor(&sdPipeDescriptor,
- SECURITY_DESCRIPTOR_REVISION) )
- {
- sql_perror("Can't start server : Initialize security descriptor");
- unireg_abort(1);
- }
- if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
- {
- sql_perror("Can't start server : Set security descriptor");
- unireg_abort(1);
- }
- saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES );
- saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
- saPipeSecurity.bInheritHandle = FALSE;
- if ((hPipe = CreateNamedPipe(szPipeName,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_BYTE |
- PIPE_READMODE_BYTE |
- PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES,
- (int) net_buffer_length,
- (int) net_buffer_length,
- NMPWAIT_USE_DEFAULT_WAIT,
- &saPipeSecurity )) == INVALID_HANDLE_VALUE)
- {
- LPVOID lpMsgBuf;
- int error=GetLastError();
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL );
- MessageBox( NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
- MB_OK|MB_ICONINFORMATION );
- LocalFree( lpMsgBuf );
- unireg_abort(1);
- }
- }
- #endif
- #if defined(HAVE_SYS_UN_H)
- /*
- ** Create the UNIX socket
- */
- if (mysql_unix_port[0] && !opt_bootstrap)
- {
- DBUG_PRINT("general",("UNIX Socket is %s",mysql_unix_port));
- if ((unix_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
- {
- sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
- unireg_abort(1); /* purecov: inspected */
- }
- bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
- UNIXaddr.sun_family = AF_UNIX;
- strmov(UNIXaddr.sun_path, mysql_unix_port);
- (void) unlink(mysql_unix_port);
- (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
- sizeof(arg));
- umask(0);
- if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
- sizeof(UNIXaddr)) < 0)
- {
- sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
- sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysql_unix_port);
- unireg_abort(1); /* purecov: tested */
- }
- umask(((~my_umask) & 0666));
- #if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
- (void) chmod(mysql_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */
- #endif
- if (listen(unix_sock,(int) back_log) < 0)
- sql_print_error("Warning: listen() on Unix socket failed with error %d",
- errno);
- }
- #endif
- DBUG_PRINT("info",("server started"));
- DBUG_VOID_RETURN;
- }
- void yyerror(const char *s)
- {
- NET *net=my_pthread_getspecific_ptr(NET*,THR_NET);
- char *yytext=(char*) current_lex->tok_start;
- if (!strcmp(s,"parse error"))
- s=ER(ER_SYNTAX_ERROR);
- net_printf(net,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
- current_lex->yylineno);
- }
- void close_connection(NET *net,uint errcode,bool lock)
- {
- Vio* vio;
- DBUG_ENTER("close_connection");
- DBUG_PRINT("enter",("fd: %s error: '%s'",
- net->vio? vio_description(net->vio):"(not connected)",
- errcode ? ER(errcode) : ""));
- if (lock)
- (void) pthread_mutex_lock(&LOCK_thread_count);
- if ((vio=net->vio) != 0)
- {
- if (errcode)
- send_error(net,errcode,ER(errcode)); /* purecov: inspected */
- vio_close(vio); /* vio is freed in delete thd */
- }
- if (lock)
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_VOID_RETURN;
- }
- /* Called when a thread is aborted */
- /* ARGSUSED */
- sig_handler end_thread_signal(int sig __attribute__((unused)))
- {
- THD *thd=current_thd;
- DBUG_ENTER("end_thread_signal");
- if (thd)
- end_thread(thd,0);
- DBUG_VOID_RETURN; /* purecov: deadcode */
- }
- void end_thread(THD *thd, bool put_in_cache)
- {
- DBUG_ENTER("end_thread");
- (void) pthread_mutex_lock(&LOCK_thread_count);
- thread_count--;
- delete thd;
- if (put_in_cache && cached_thread_count < thread_cache_size &&
- ! abort_loop && !kill_cached_threads)
- {
- /* Don't kill the thread, just put it in cache for reuse */
- DBUG_PRINT("info", ("Adding thread to cache"))
- cached_thread_count++;
- while (!abort_loop && ! wake_thread && ! kill_cached_threads)
- (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
- cached_thread_count--;
- if (kill_cached_threads)
- pthread_cond_signal(&COND_flush_thread_cache);
- if (wake_thread)
- {
- wake_thread--;
- thd=thread_cache.get();
- thd->real_id=pthread_self();
- (void) thd->store_globals();
- threads.append(thd);
- pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_VOID_RETURN;
- }
- }
- DBUG_PRINT("info", ("sending a broadcast"))
- /* Tell main we are ready */
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- (void) pthread_cond_broadcast(&COND_thread_count);
- DBUG_PRINT("info", ("unlocked thread_count mutex"))
- #ifdef ONE_THREAD
- if (!(test_flags & TEST_NO_THREADS)) // For debugging under Linux
- #endif
- {
- my_thread_end();
- pthread_exit(0);
- }
- DBUG_VOID_RETURN;
- }
- /* Start a cached thread. LOCK_thread_count is locked on entry */
- static void start_cached_thread(THD *thd)
- {
- thread_cache.append(thd);
- wake_thread++;
- thread_count++;
- pthread_cond_signal(&COND_thread_cache);
- }
- void flush_thread_cache()
- {
- (void) pthread_mutex_lock(&LOCK_thread_count);
- kill_cached_threads++;
- while (cached_thread_count)
- {
- pthread_cond_broadcast(&COND_thread_cache);
- pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count);
- }
- kill_cached_threads--;
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- }
- /*
- ** Aborts a thread nicely. Commes here on SIGPIPE
- ** TODO: One should have to fix that thr_alarm know about this
- ** thread too
- */
- #ifdef THREAD_SPECIFIC_SIGPIPE
- static sig_handler abort_thread(int sig __attribute__((unused)))
- {
- THD *thd=current_thd;
- DBUG_ENTER("abort_thread");
- if (thd)
- thd->killed=1;
- DBUG_VOID_RETURN;
- }
- #endif
- /******************************************************************************
- ** Setup a signal thread with handles all signals
- ** Because linux doesn't support scemas use a mutex to check that
- ** the signal thread is ready before continuing
- ******************************************************************************/
- #ifdef __WIN__
- static void init_signals(void)
- {
- int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
- for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
- signal( signals[i], kill_server) ;
- signal(SIGBREAK,SIG_IGN); //ignore SIGBREAK for NT
- }
- #elif defined(__EMX__)
- static void sig_reload(int signo)
- {
- reload_acl_and_cache((THD*) 0,~0, (TABLE_LIST*) 0); // Flush everything
- signal(signo, SIG_ACK);
- }
- static void sig_kill(int signo)
- {
- if (!abort_loop)
- {
- abort_loop=1; // mark abort for threads
- kill_server((void*) signo);
- }
- signal(signo, SIG_ACK);
- }
- static void init_signals(void)
- {
- signal(SIGQUIT, sig_kill);
- signal(SIGKILL, sig_kill);
- signal(SIGTERM, sig_kill);
- signal(SIGINT, sig_kill);
- signal(SIGHUP, sig_reload); // Flush everything
- signal(SIGALRM, SIG_IGN);
- signal(SIGBREAK,SIG_IGN);
- signal_thread = pthread_self();
- }
- #else /* if ! __WIN__ && ! __EMX__ */
- #ifdef HAVE_LINUXTHREADS
- static sig_handler write_core(int sig);
- #ifdef __i386__
- #define SIGRETURN_FRAME_COUNT 1
- #define PTR_SANE(p) ((char*)p >= heap_start && (char*)p <= heap_end)
- extern char* __bss_start;
- static char* heap_start, *heap_end;
- inline __volatile__ void print_str(const char* name,
- const char* val, int max_len)
- {
- fprintf(stderr, "%s at %p ", name, val);
- if(!PTR_SANE(val))
- {
- fprintf(stderr, " is invalid pointern");
- return;
- }
- fprintf(stderr, "= ");
- for(; max_len && PTR_SANE(val) && *val; --max_len)
- fputc(*val++, stderr);
- fputc('n', stderr);
- }
- inline __volatile__ void trace_stack()
- {
- uchar **stack_bottom;
- uchar** ebp;
- LINT_INIT(ebp);
- LINT_INIT(stack_bottom);
- fprintf(stderr,
- "Attempting backtrace. You can use the following information to find outn
- where mysqld died. If you see no messages after this, something wentn
- terribly wrong...n");
- THD* thd = current_thd;
- uint frame_count = 0;
- __asm __volatile__ ("movl %%ebp,%0"
- :"=r"(ebp)
- :"r"(ebp));
- if (!ebp)
- {
- fprintf(stderr, "frame pointer (ebp) is NULL, did you compile withn
- -fomit-frame-pointer? Aborting backtrace!n");
- return;
- }
- if (!thd)
- {
- fprintf(stderr, "Cannot determine thread, ebp=%p, backtrace may not be correct.n", ebp);
- /* Assume that the stack starts at the previous even 65K */
- ulong tmp= min(0x10000,thread_stack);
- stack_bottom= (uchar**) (((ulong) &stack_bottom + tmp) &
- ~(ulong) 0xFFFF);
- }
- else
- stack_bottom = (uchar**) thd->thread_stack;
- if (ebp > stack_bottom || ebp < stack_bottom - thread_stack)
- {
- fprintf(stderr,
- "Bogus stack limit or frame pointer, aborting backtrace.n");
- return;
- }
- fprintf(stderr, "Stack range sanity check OK, backtrace follows:n");
-
- while (ebp < stack_bottom)
- {
- uchar** new_ebp = (uchar**)*ebp;
- fprintf(stderr, "%pn", frame_count == SIGRETURN_FRAME_COUNT ?
- *(ebp+17) : *(ebp+1));
- if (new_ebp <= ebp )
- {
- fprintf(stderr, "
- New value of ebp failed sanity check, terminating backtrace!n");
- return;
- }
- ebp = new_ebp;
- ++frame_count;
- }
- fprintf(stderr, "Stack trace successful, trying to get some variables.n
- Some pointers may be invalid and cause the dump to abort...n");
- heap_start = __bss_start;
- heap_end = (char*)sbrk(0);
- print_str("thd->query", thd->query, 1024);
- fprintf(stderr, "thd->thread_id = %ldn", thd->thread_id);
- fprintf(stderr, "Successfully dumped variables, if you ran with --log,n
- take a look at the details of what thread %ld did to cause the crash.n
- In some cases of really bad corruption, this value may be invalidn",
- thd->thread_id);
- fprintf(stderr, "Please use the information above to create a repeatablen
- test case for the crash, and send it to bugs@lists.mysql.comn");
- }
- #endif
- #endif
- static sig_handler handle_segfault(int sig)
- {
- // strictly speaking, one needs a mutex here
- // but since we have got SIGSEGV already, things are a mess
- // so not having the mutex is not as bad as possibly using a buggy
- // mutex - so we keep things simple
- if (segfaulted)
- return;
- segfaulted = 1;
- fprintf(stderr,"
- mysqld got signal %d;n
- The manual section 'Debugging a MySQL server' tells you how to use an
- stack trace and/or the core file to produce a readable backtrace that mayn
- help in finding out why mysqld died.n",sig);
- #if defined(HAVE_LINUXTHREADS)
- #ifdef __i386__
- trace_stack();
- #endif /* __i386__ */
- if (test_flags & TEST_CORE_ON_SIGNAL)
- write_core(sig);
- #endif /* HAVE_LINUXTHREADS */
- exit(1);
- }
- /* Produce a core for the thread */
- #ifdef HAVE_LINUXTHREADS
- static sig_handler write_core(int sig)
- {
- signal(sig, SIG_DFL);
- if (fork() != 0) exit(1); // Abort main program
- // Core will be written at exit
- }
- #endif
- static void init_signals(void)
- {
- sigset_t set;
- pthread_attr_t thr_attr;
- int error;
- DBUG_ENTER("init_signals");
- sigset(THR_KILL_SIGNAL,end_thread_signal);
- sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
- struct sigaction sa; sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
- if (!(test_flags & TEST_NO_STACKTRACE))
- {
- #ifdef HAVE_DARWIN_THREADS
- sa.sa_handler=( void (*)() ) handle_segfault;
- #else
- sa.sa_handler=handle_segfault;
- #endif
- sigaction(SIGSEGV, &sa, NULL);
- #ifdef SIGBUS
- sigaction(SIGBUS, &sa, NULL);
- #endif
- sigaction(SIGILL, &sa, NULL);
- }
- (void) sigemptyset(&set);
- #ifdef THREAD_SPECIFIC_SIGPIPE
- sigset(SIGPIPE,abort_thread);
- sigaddset(&set,SIGPIPE);
- #else
- (void) signal(SIGPIPE,SIG_IGN); // Can't know which thread
- sigaddset(&set,SIGPIPE);
- #endif
- sigaddset(&set,SIGINT);
- sigaddset(&set,SIGQUIT);
- sigaddset(&set,SIGTERM);
- sigaddset(&set,SIGHUP);
- signal(SIGTERM,SIG_DFL); // If it's blocked by parent
- signal(SIGHUP,SIG_DFL); // If it's blocked by parent
- #ifdef SIGTSTP
- sigaddset(&set,SIGTSTP);
- #endif
- sigaddset(&set,THR_SERVER_ALARM);
- sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
- sigdelset(&set,THR_CLIENT_ALARM); // For alarms
- (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
- (void) pthread_attr_init(&thr_attr);
- #if !defined(HAVE_DEC_3_2_THREADS)
- pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
- (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
- pthread_attr_setstacksize(&thr_attr,32768);
- #endif
- (void) pthread_mutex_lock(&LOCK_thread_count);
- if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
- {
- sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
- error,errno);
- exit(1);
- }
- (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- pthread_mutex_unlock(&LOCK_thread_count);
- (void) pthread_attr_destroy(&thr_attr);
- DBUG_VOID_RETURN;
- }
- /*
- ** This threads handles all signals and alarms
- */
- /* ARGSUSED */
- static void *signal_hand(void *arg __attribute__((unused)))
- {
- sigset_t set;
- int sig;
- my_thread_init(); // Init new thread
- DBUG_ENTER("signal_hand");
- /* Setup alarm handler */
- init_thr_alarm(max_connections+max_insert_delayed_threads);
- #if SIGINT != THR_KILL_SIGNAL
- (void) sigemptyset(&set); // Setup up SIGINT for debug
- (void) sigaddset(&set,SIGINT); // For debugging
- (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
- #endif
- (void) sigemptyset(&set); // Setup up SIGINT for debug
- #ifdef USE_ONE_SIGNAL_HAND
- (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
- #endif
- (void) sigaddset(&set,SIGQUIT);
- (void) sigaddset(&set,SIGTERM);
- #if THR_CLIENT_ALARM != SIGHUP
- (void) sigaddset(&set,SIGHUP);
- #endif
- (void) sigaddset(&set,SIGTSTP);
- /* Save pid to this process (or thread on Linux) */
- if (!opt_bootstrap)
- {
- File pidFile;
- if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0)
- {
- char buff[21];
- sprintf(buff,"%lu",(ulong) getpid());
- (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME));
- (void) my_close(pidFile,MYF(0));
- }
- }
- (void) pthread_mutex_lock(&LOCK_thread_count);
- (void) pthread_cond_signal(&COND_thread_count); /* continue init_signals */
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- for (;;)
- {
- int error; // Used when debugging
- if (shutdown_in_progress && !abort_loop)
- {
- sig=SIGTERM;
- error=0;
- }
- else
- while ((error=my_sigwait(&set,&sig)) == EINTR) ;
- if (cleanup_done)
- pthread_exit(0); // Safety
- switch (sig) {
- case SIGTERM:
- case SIGQUIT:
- case SIGKILL:
- #ifdef EXTRA_DEBUG
- sql_print_error("Got signal %d to shutdown mysqld",sig);
- #endif
- DBUG_PRINT("info",("Got signal: %d abort_loop: %d",sig,abort_loop));
- if (!abort_loop)
- {
- abort_loop=1; // mark abort for threads
- #ifdef USE_ONE_SIGNAL_HAND
- pthread_t tmp;
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
- if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
- (void*) sig))
- sql_print_error("Error: Can't create thread to kill server");
- #else
- kill_server((void*) sig); // MIT THREAD has a alarm thread
- #endif
- }
- break;
- case SIGHUP:
- reload_acl_and_cache((THD*) 0,~0, (TABLE_LIST*) 0); // Flush everything
- mysql_print_status((THD*) 0); // Send debug some info
- break;
- #ifdef USE_ONE_SIGNAL_HAND
- case THR_SERVER_ALARM:
- process_alarm(sig); // Trigger alarms.
- break;
- #endif
- default:
- #ifdef EXTRA_DEBUG
- sql_print_error("Warning: Got signal: %d, error: %d",sig,error); /* purecov: tested */
- #endif
- break; /* purecov: tested */
- }
- }
- return(0); /* purecov: deadcode */
- }
- #endif /* __WIN__*/
- /*
- ** All global error messages are sent here where the first one is stored for
- ** the client
- */
- /* ARGSUSED */
- static int my_message_sql(uint error, const char *str,
- myf MyFlags __attribute__((unused)))
- {
- NET *net;
- DBUG_ENTER("my_message_sql");
- DBUG_PRINT("error",("Message: '%s'",str));
- if ((net=my_pthread_getspecific_ptr(NET*,THR_NET)))
- {
- if (!net->last_error[0]) // Return only first message
- {
- strmake(net->last_error,str,sizeof(net->last_error)-1);
- net->last_errno=error ? error : ER_UNKNOWN_ERROR;
- }
- }
- else
- sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
- DBUG_RETURN(0);
- }
- #ifdef __WIN__
- #undef errno
- #undef EINTR
- #define errno WSAGetLastError()
- #define EINTR WSAEINTR
- struct utsname
- {
- char nodename[FN_REFLEN];
- };
- int uname(struct utsname *a)
- {
- return -1;
- }
- #endif
- #ifdef __WIN__
- pthread_handler_decl(handle_shutdown,arg)
- {
- MSG msg;
- my_thread_init();
- /* this call should create the message queue for this thread */
- PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
- if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
- kill_server(MYSQL_KILL_SIGNAL);
- return 0;
- }
- int __stdcall handle_kill(ulong ctrl_type)
- {
- if (ctrl_type == CTRL_CLOSE_EVENT ||
- ctrl_type == CTRL_SHUTDOWN_EVENT)
- {
- kill_server(MYSQL_KILL_SIGNAL);
- return TRUE;
- }
- return FALSE;
- }
- #endif
- const char *load_default_groups[]= { "mysqld","server",0 };
- #ifdef HAVE_LIBWRAP
- char *libwrapName=NULL;
- #endif
- static void open_log(MYSQL_LOG *log, const char *hostname,
- const char *opt_name, const char *extension,
- enum_log_type type)
- {
- char tmp[FN_REFLEN];
- if (!opt_name || !opt_name[0])
- {
- /* TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,hostname,FN_REFLEN-5);
- strmov(strcend(tmp,'.'),extension);
- opt_name=tmp;
- }
- log->open(opt_name,type);
- }
- #ifdef __WIN__
- int win_main(int argc, char **argv)
- #else
- int main(int argc, char **argv)
- #endif
- {
- DEBUGGER_OFF;
- my_umask=0660; // Default umask for new files
- my_umask_dir=0700; // Default umask for new directories
- MY_INIT(argv[0]); // init my_sys library & pthreads
- tzset(); // Set tzname
- start_time=time((time_t*) 0);
- #ifdef HAVE_TZNAME
- #if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
- {
- struct tm tm_tmp;
- localtime_r(&start_time,&tm_tmp);
- strmov(time_zone,tzname[tm_tmp.tm_isdst == 1 ? 1 : 0]);
- }
- #else
- {
- struct tm *start_tm;
- start_tm=localtime(&start_time);
- strmov(time_zone,tzname[start_tm->tm_isdst == 1 ? 1 : 0]);
- }
- #endif
- #endif
- if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
- strmov(glob_hostname,"mysql");
- strmov(pidfile_name,glob_hostname);
- strmov(strcend(pidfile_name,'.'),".pid"); // Add extension
- #ifndef DBUG_OFF
- strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
- #else
- strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
- #endif
- #ifdef _CUSTOMSTARTUPCONFIG_
- if (_cust_check_startup())
- {
- /* _cust_check_startup will report startup failure error */
- exit( 1 );
- }
- #endif
- load_defaults("my",load_default_groups,&argc,&argv);
- defaults_argv=argv;
- mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
- #ifdef __WIN__
- if (!mysql_tmpdir)
- mysql_tmpdir=getenv("TEMP");
- if (!mysql_tmpdir)
- mysql_tmpdir=getenv("TMP");
- #endif
- if (!mysql_tmpdir || !mysql_tmpdir[0])
- mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
- set_options();
- #ifdef __WIN__
- /* service parameters can be overwritten by options */
- if (get_service_parameters())
- {
- my_message( 0, "Can't read MySQL service parameters", MYF(0) );
- exit( 1 );
- }
- #endif
- get_options(argc,argv);
- if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
- strcat(server_version,"-log");
- DBUG_PRINT("info",("%s Ver %s for %s on %sn",my_progname,
- server_version, SYSTEM_TYPE,MACHINE_TYPE));
- /* These must be set early */
- (void) pthread_cond_init(&COND_thread_count,NULL);
- (void) pthread_mutex_init(&LOCK_mysql_create_db,NULL);
- (void) pthread_mutex_init(&LOCK_Acl,NULL);
- (void) pthread_mutex_init(&LOCK_grant,NULL);
- (void) pthread_mutex_init(&LOCK_open,NULL);
- (void) pthread_mutex_init(&LOCK_thread_count,NULL);
- (void) pthread_mutex_init(&LOCK_mapped_file,NULL);
- (void) pthread_mutex_init(&LOCK_status,NULL);
- (void) pthread_mutex_init(&LOCK_error_log,NULL);
- (void) pthread_mutex_init(&LOCK_delayed_insert,NULL);
- (void) pthread_mutex_init(&LOCK_delayed_status,NULL);
- (void) pthread_mutex_init(&LOCK_delayed_create,NULL);
- (void) pthread_cond_init(&COND_refresh,NULL);
- (void) pthread_cond_init(&COND_thread_cache,NULL);
- (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
- (void) pthread_cond_init(&COND_manager,NULL);
- (void) pthread_mutex_init(&LOCK_manager,NULL);
- (void) pthread_mutex_init(&LOCK_crypt,NULL);
- (void) pthread_mutex_init(&LOCK_bytes_sent,NULL);
- (void) pthread_mutex_init(&LOCK_bytes_received,NULL);
- (void) pthread_mutex_init(&LOCK_timezone,NULL);
- (void) pthread_mutex_init(&LOCK_binlog_update, NULL);
- (void) pthread_mutex_init(&LOCK_slave, NULL);
- (void) pthread_mutex_init(&LOCK_server_id, NULL);
- (void) pthread_mutex_init(&LOCK_user_conn, NULL);
- (void) pthread_cond_init(&COND_binlog_update, NULL);
- (void) pthread_cond_init(&COND_slave_stopped, NULL);
- (void) pthread_cond_init(&COND_slave_start, NULL);
- if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
- unireg_abort(1);
- charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));
- #ifdef HAVE_OPENSSL
- if (opt_use_ssl)
- {
- ssl_acceptor_fd = VioSSLAcceptorFd_new(opt_ssl_key, opt_ssl_cert,
- opt_ssl_ca, opt_ssl_capath);
- if (!ssl_acceptor_fd)
- opt_use_ssl=0;
- /* having ssl_acceptor_fd!=0 signals the use of SSL */
- }
- #endif /* HAVE_OPENSSL */
- #ifdef HAVE_LIBWRAP
- libwrapName= my_progname+dirname_length(my_progname);
- openlog(libwrapName, LOG_PID, LOG_AUTH);
- #endif
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
- /* Parameter for threads created for connections */
- (void) pthread_attr_init(&connection_attrib);
- (void) pthread_attr_setdetachstate(&connection_attrib,
- PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&connection_attrib,thread_stack);
- if (!(opt_specialflag & SPECIAL_NO_PRIOR))
- my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
- pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
- #ifdef SET_RLIMIT_NOFILE
- /* connections and databases neads lots of files */
- {
- uint wanted_files=10+(uint) max(max_connections*5,
- max_connections+table_cache_size*2);
- set_if_bigger(wanted_files, open_files_limit);
- // Note that some system returns 0 if we succeed here:
- uint files=set_maximum_open_files(wanted_files);
- if (files && files < wanted_files && ! open_files_limit)
- {
- max_connections= (ulong) min((files-10),max_connections);
- table_cache_size= (ulong) max((files-10-max_connections)/2,64);
- DBUG_PRINT("warning",
- ("Changed limits: max_connections: %ld table_cache: %ld",
- max_connections,table_cache_size));
- sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size);
- }
- }
- #endif
- unireg_init(opt_specialflag); /* Set up extern variabels */
- init_errmessage(); /* Read error messages from file */
- lex_init();
- item_init();
- mysys_uses_curses=0;
- #ifdef USE_REGEX
- regex_init();
- #endif
- select_thread=pthread_self();
- select_thread_in_use=1;
- if (use_temp_pool && bitmap_init(&temp_pool,1024))
- unireg_abort(1);
- /*
- ** We have enough space for fiddling with the argv, continue
- */
- umask(((~my_umask) & 0666));
- if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
- {
- unireg_abort(1); /* purecov: inspected */
- }
- mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
- mysql_data_home[1]=0;
- server_init();
- table_cache_init();
- hostname_cache_init();
- sql_cache_init();
- randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
- reset_floating_point_exceptions();
- init_thr_lock();
- /* Setup log files */
- if (opt_log)
- open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL);
- if (opt_update_log)
- open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
- LOG_NEW);
- if (opt_bin_log && !server_id)
- {
- server_id= !master_host ? 1 : 2;
- switch (server_id) {
- #ifdef EXTRA_DEBUG
- case 1:
- sql_print_error("
- Warning: You should set server-id to a non-0 value if log-bin is enabled.n
- mysqld will log updates to the binary log, but will not accept connectionsn
- from slaves.");
- break;
- #endif
- case 2:
- sql_print_error("
- Warning: You should set server-id to a non-0 value if master_host is set.n
- The server will not act as a slave.");
- break;
- }
- }
- if (opt_bin_log)
- {
- if (!opt_bin_logname)
- {
- char tmp[FN_REFLEN];
- /* TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,glob_hostname,FN_REFLEN-5);
- strmov(strcend(tmp,'.'),"-bin");
- opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
- }
- mysql_bin_log.set_index_file_name(opt_binlog_index_name);
- open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
- LOG_BIN);
- }
-
- if (opt_slow_log)
- open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
- LOG_NORMAL);
- if (ha_init())
- {
- sql_print_error("Can't init databases");
- exit(1);
- }
- #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
- if (locked_in_memory && !geteuid())
- {
- ha_key_cache();
- if (mlockall(MCL_CURRENT))
- {
- sql_print_error("Warning: Failed to lock memory. Errno: %dn",errno);
- }
- else
- locked_in_memory=1;
- }
- #else
- locked_in_memory=0;
- #endif
- if (opt_myisam_log)
- (void) mi_log( 1 );
- ft_init_stopwords(ft_precompiled_stopwords); /* SerG */
- #ifdef __WIN__
- #define MYSQL_ERR_FILE "mysql.err"
- if (!opt_console)
- {
- freopen(MYSQL_ERR_FILE,"a+",stdout);
- freopen(MYSQL_ERR_FILE,"a+",stderr);
- FreeConsole(); // Remove window
- }
- #endif
- /*
- init signals & alarm
- After this we can't quit by a simple unireg_abort
- */
- error_handler_hook = my_message_sql;
- if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
- pthread_key_create(&THR_MALLOC,NULL))
- {
- sql_print_error("Can't create thread-keys");
- exit(1);
- }
- init_signals(); // Creates pidfile
- if (acl_init(opt_noacl))
- {
- select_thread_in_use=0;
- (void) pthread_kill(signal_thread,MYSQL_KILL_SIGNAL);
- #ifndef __WIN__
- if (!opt_bootstrap)
- (void) my_delete(pidfile_name,MYF(MY_WME)); // Not neaded anymore
- #endif
- exit(1);
- }
- if (!opt_noacl)
- (void) grant_init();
- if (max_user_connections)
- init_max_user_conn();
- #ifdef HAVE_DLOPEN
- if (!opt_noacl)
- udf_init();
- #endif
- if (opt_bootstrap)
- {
- int error=bootstrap(stdin);
- end_thr_alarm(); // Don't allow alarms
- unireg_abort(error ? 1 : 0);
- }
- if (opt_init_file)
- {
- if (read_init_file(opt_init_file))
- {
- end_thr_alarm(); // Don't allow alarms
- unireg_abort(1);
- }
- }
- (void) thr_setconcurrency(concurrency); // 10 by default
- #ifdef __WIN__ //IRENA
- {
- hEventShutdown=CreateEvent(0, FALSE, FALSE, "MySqlShutdown");
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
- sql_print_error("Warning: Can't create thread to handle shutdown requests");
- // On "Stop Service" we have to do regular shutdown
- Service.SetShutdownEvent(hEventShutdown);
- }
- #endif
- if (
- #ifdef HAVE_BERKELEY_DB
- !berkeley_skip ||
- #endif
- (flush_time && flush_time != ~(ulong) 0L))
- {
- pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
- sql_print_error("Warning: Can't create thread to manage maintenance");
- }
- // slave thread
- if (master_host)
- {
- pthread_t hThread;
- if (!opt_skip_slave_start &&
- pthread_create(&hThread, &connection_attrib, handle_slave, 0))
- sql_print_error("Warning: Can't create thread to handle slave");
- else if(opt_skip_slave_start)
- init_master_info(&glob_mi);
- }
- printf(ER(ER_READY),my_progname,server_version,"");
- fflush(stdout);
- #ifdef __NT__
- if (hPipe == INVALID_HANDLE_VALUE && !have_tcpip)
- {
- sql_print_error("TCP/IP must be installed on Win98 platforms");
- }
- else
- {
- pthread_mutex_lock(&LOCK_thread_count);
- (void) pthread_cond_init(&COND_handler_count,NULL);
- {
- pthread_t hThread;
- handler_count=0;
- if ( hPipe != INVALID_HANDLE_VALUE )
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_namedpipes, 0))
- {
- sql_print_error("Warning: Can't create thread to handle named pipes");
- handler_count--;
- }
- }
- if (have_tcpip && !opt_disable_networking)
- {
- handler_count++;
- if (pthread_create(&hThread,&connection_attrib,
- handle_connections_sockets, 0))
- {
- sql_print_error("Warning: Can't create thread to handle named pipes");
- handler_count--;
- }
- }
- while (handler_count > 0)
- {
- pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
- }
- }
- pthread_mutex_unlock(&LOCK_thread_count);
- }
- #else
- handle_connections_sockets(0);
- #ifdef EXTRA_DEBUG
- sql_print_error("Exiting main thread");
- #endif
- #endif /* __NT__ */
- /* (void) pthread_attr_destroy(&connection_attrib); */
- DBUG_PRINT("quit",("Exiting main thread"));
- #ifndef __WIN__
- #ifdef EXTRA_DEBUG
- sql_print_error("Before Lock_thread_count");
- #endif
- (void) pthread_mutex_lock(&LOCK_thread_count);
- select_thread_in_use=0; // For close_connections
- (void) pthread_cond_broadcast(&COND_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- #ifdef EXTRA_DEBUG
- sql_print_error("After lock_thread_count");
- #endif
- #else
- // remove the event, because it will not be valid anymore
- Service.SetShutdownEvent(0);
- if(hEventShutdown) CloseHandle(hEventShutdown);
- // if it was started as service on NT try to stop the service
- if(Service.IsNT())
- Service.Stop();
- #endif
- /* Wait until cleanup is done */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (!ready_to_exit)
- {
- pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
- exit(0);
- return(0); /* purecov: deadcode */
- }
- #ifdef __WIN__
- /* ------------------------------------------------------------------------
- main and thread entry function for Win32
- (all this is needed only to run mysqld as a service on WinNT)
- -------------------------------------------------------------------------- */
- int mysql_service(void *p)
- {
- win_main(Service.my_argc, Service.my_argv);
- return 0;
- }
- int main(int argc, char **argv)
- {
- // check environment variable OS
- if (Service.GetOS()) // "OS" defined; Should be NT
- {
- if (argc == 2)
- {
- if (!strcmp(argv[1],"-install") || !strcmp(argv[1],"--install"))
- {
- char path[FN_REFLEN];
- my_path(path, argv[0], ""); // Find name in path
- fn_format(path,argv[0],path,"",1+4+16); // Force use of full path
- if (!Service.Install(MYSQL_SERVICENAME,MYSQL_SERVICENAME,path))
- MessageBox(NULL,"Failed to install Service",MYSQL_SERVICENAME,
- MB_OK|MB_ICONSTOP);
- return 0;
- }
- else if (!strcmp(argv[1],"-remove") || !strcmp(argv[1],"--remove"))
- {
- Service.Remove(MYSQL_SERVICENAME);
- return 0;
- }
- }
- else if (argc == 1) // No arguments; start as a service
- {
- // init service
- long tmp=Service.Init(MYSQL_SERVICENAME,mysql_service);
- return 0;
- }
- }
- // This is a WIN95 machine or a start of mysqld as a standalone program
- // we have to pass the arguments, in case of NT-service this will be done
- // by ServiceMain()
- Service.my_argc=argc;
- Service.my_argv=argv;
- mysql_service(NULL);
- return 0;
- }
- /* ------------------------------------------------------------------------ */
- #endif
- static int bootstrap(FILE *file)
- {
- THD *thd= new THD;
- int error;
- thd->bootstrap=1;
- thd->client_capabilities=0;
- my_net_init(&thd->net,(Vio*) 0);
- thd->max_packet_length=thd->net.max_packet;
- thd->master_access= ~0;
- thd->thread_id=thread_id++;
- thread_count++;
- bootstrap_file=file;
- if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap,
- (void*) thd))
- {
- sql_print_error("Warning: Can't create thread to handle bootstrap");
- return -1;
- }
- /* Wait for thread to die */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- while (thread_count)
- {
- (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- error= thd->fatal_error;
- net_end(&thd->net);
- delete thd;
- return error;
- }
- static bool read_init_file(char *file_name)
- {
- FILE *file;
- DBUG_ENTER("read_init_file");
- DBUG_PRINT("enter",("name: %s",file_name));
- if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME))))
- return(1);
- bootstrap(file); /* Ignore errors from this */
- (void) my_fclose(file,MYF(MY_WME));
- return 0;
- }
- static void create_new_thread(THD *thd)
- {
- DBUG_ENTER("create_new_thread");
- NET *net=&thd->net; // For easy ref
- net->timeout = (uint) connect_timeout; // Timeout for read
- if (protocol_version > 9)
- net->return_errno=1;
- /* don't allow too many connections */
- if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop)
- {
- DBUG_PRINT("error",("Too many connections"));
- close_connection(net,ER_CON_COUNT_ERROR);
- delete thd;
- DBUG_VOID_RETURN;
- }
- if (pthread_mutex_lock(&LOCK_thread_count))
- {
- DBUG_PRINT("error",("Can't lock LOCK_thread_count"));
- close_connection(net,ER_OUT_OF_RESOURCES);
- delete thd;
- DBUG_VOID_RETURN;
- }
- if (thread_count-delayed_insert_threads > max_used_connections)
- max_used_connections=thread_count-delayed_insert_threads;
- thd->thread_id=thread_id++;
- for (uint i=0; i < 8 ; i++) // Generate password teststring
- thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
- thd->scramble[8]=0;
- thd->rand=sql_rand;
- thd->real_id=pthread_self(); // Keep purify happy
- /* Start a new thread to handle connection */
- #ifdef ONE_THREAD
- if (test_flags & TEST_NO_THREADS) // For debugging under Linux
- {
- thread_cache_size=0; // Safety
- thread_count++;
- threads.append(thd);
- thd->real_id=pthread_self();
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- handle_one_connection((void*) thd);
- }
- else
- #endif
- {
- if (cached_thread_count > wake_thread)
- {
- start_cached_thread(thd);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- }
- else
- {
- int error;
- thread_count++;
- thread_created++;
- threads.append(thd);
- DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
- thd->connect_time = time(NULL);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- if ((error=pthread_create(&thd->real_id,&connection_attrib,
- handle_one_connection,