mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-32567 Remove thr_alarm from server codebase
This allows to simplify net_real_read() and net_real_write() a bit. Removed some superfluous #ifdef/ifndef MYSQL_SERVER from net_serv.cc The code always runs in server, either normal or embedded. Dead code for switching socket between blocking and non-blocking modes, is also removed. Removed pthread_kill() with alarm signal that woke up main thread on server shutdown. Used shutdown(2) on polling sockets instead, to the same effect. Removed yet another superstitious pthread_kill(), that ran on non-Windows in terminate_slave_thread().
This commit is contained in:
parent
3424ed7d42
commit
013fc02a23
19 changed files with 125 additions and 1515 deletions
|
@ -384,7 +384,6 @@
|
|||
#cmakedefine HAVE_GCC_C11_ATOMICS 1
|
||||
#cmakedefine HAVE_SOLARIS_ATOMIC 1
|
||||
#cmakedefine NO_FCNTL_NONBLOCK 1
|
||||
#cmakedefine NO_ALARM 1
|
||||
|
||||
#cmakedefine _LARGE_FILES 1
|
||||
#cmakedefine _LARGEFILE_SOURCE 1
|
||||
|
|
|
@ -836,7 +836,6 @@ CHECK_CXX_SOURCE_COMPILES("
|
|||
"
|
||||
HAVE_SOLARIS_STYLE_GETHOST)
|
||||
|
||||
SET(NO_ALARM 1 CACHE BOOL "No need to use alarm to implement timeout")
|
||||
|
||||
# As a consequence of ALARMs no longer being used, thread
|
||||
# notification for KILL must close the socket to wake up
|
||||
|
|
|
@ -181,7 +181,6 @@ extern int my_pthread_create_detached;
|
|||
#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached
|
||||
#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_GLOBAL
|
||||
#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL
|
||||
#define USE_ALARM_THREAD
|
||||
#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */
|
||||
|
||||
#if defined(_BSDI_VERSION) && _BSDI_VERSION < 199910
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
/* Prototypes when using thr_alarm library functions */
|
||||
|
||||
#ifndef _thr_alarm_h
|
||||
#define _thr_alarm_h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef USE_ALARM_THREAD
|
||||
#define USE_ONE_SIGNAL_HAND /* One must call process_alarm */
|
||||
#endif
|
||||
#ifdef HAVE_rts_threads
|
||||
#undef USE_ONE_SIGNAL_HAND
|
||||
#define USE_ALARM_THREAD
|
||||
#define THR_SERVER_ALARM SIGUSR1
|
||||
#else
|
||||
#define THR_SERVER_ALARM SIGALRM
|
||||
#endif
|
||||
|
||||
typedef struct st_alarm_info
|
||||
{
|
||||
time_t next_alarm_time;
|
||||
uint active_alarms;
|
||||
uint max_used_alarms;
|
||||
} ALARM_INFO;
|
||||
|
||||
void thr_alarm_info(ALARM_INFO *info);
|
||||
extern my_bool my_disable_thr_alarm;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DONT_USE_THR_ALARM
|
||||
#endif
|
||||
#if defined(DONT_USE_THR_ALARM)
|
||||
|
||||
#define USE_ALARM_THREAD
|
||||
#undef USE_ONE_SIGNAL_HAND
|
||||
|
||||
typedef my_bool thr_alarm_t;
|
||||
typedef my_bool ALARM;
|
||||
|
||||
#define thr_alarm_init(A) (*(A))=0
|
||||
#define thr_alarm_in_use(A) (*(A) != 0)
|
||||
#define thr_end_alarm(A)
|
||||
#define thr_alarm(A,B,C) ((*(A)=1)-1)
|
||||
/* The following should maybe be (*(A)) */
|
||||
#define thr_got_alarm(A) 0
|
||||
#define init_thr_alarm(A)
|
||||
#define thr_alarm_kill(A)
|
||||
#define resize_thr_alarm(N)
|
||||
#define end_thr_alarm(A)
|
||||
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
typedef struct st_thr_alarm_entry
|
||||
{
|
||||
UINT_PTR crono;
|
||||
} thr_alarm_entry;
|
||||
|
||||
#else /* System with posix threads */
|
||||
|
||||
typedef int thr_alarm_entry;
|
||||
|
||||
#define thr_got_alarm(thr_alarm) (**(thr_alarm))
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
typedef thr_alarm_entry* thr_alarm_t;
|
||||
|
||||
typedef struct st_alarm {
|
||||
time_t expire_time;
|
||||
thr_alarm_entry alarmed; /* set when alarm is due */
|
||||
pthread_t thread;
|
||||
my_thread_id thread_id;
|
||||
uint index_in_queue;
|
||||
my_bool malloced;
|
||||
} ALARM;
|
||||
|
||||
extern uint thr_client_alarm;
|
||||
extern pthread_t alarm_thread;
|
||||
|
||||
#define thr_alarm_init(A) (*(A))=0
|
||||
#define thr_alarm_in_use(A) (*(A)!= 0)
|
||||
void init_thr_alarm(uint max_alarm);
|
||||
void resize_thr_alarm(uint max_alarms);
|
||||
my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
|
||||
void thr_alarm_kill(my_thread_id thread_id);
|
||||
void thr_end_alarm(thr_alarm_t *alarmed);
|
||||
void end_thr_alarm(my_bool free_structures);
|
||||
sig_handler process_alarm(int);
|
||||
#ifndef thr_got_alarm
|
||||
my_bool thr_got_alarm(thr_alarm_t *alrm);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* DONT_USE_THR_ALARM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* _thr_alarm_h */
|
|
@ -1,21 +0,0 @@
|
|||
select @@global.debug_no_thread_alarm;
|
||||
@@global.debug_no_thread_alarm
|
||||
0
|
||||
select @@session.debug_no_thread_alarm;
|
||||
ERROR HY000: Variable 'debug_no_thread_alarm' is a GLOBAL variable
|
||||
show global variables like 'debug_no_thread_alarm';
|
||||
Variable_name Value
|
||||
debug_no_thread_alarm OFF
|
||||
show session variables like 'debug_no_thread_alarm';
|
||||
Variable_name Value
|
||||
debug_no_thread_alarm OFF
|
||||
select * from information_schema.global_variables where variable_name='debug_no_thread_alarm';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
DEBUG_NO_THREAD_ALARM OFF
|
||||
select * from information_schema.session_variables where variable_name='debug_no_thread_alarm';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
DEBUG_NO_THREAD_ALARM OFF
|
||||
set global debug_no_thread_alarm=1;
|
||||
ERROR HY000: Variable 'debug_no_thread_alarm' is a read only variable
|
||||
set session debug_no_thread_alarm=1;
|
||||
ERROR HY000: Variable 'debug_no_thread_alarm' is a read only variable
|
|
@ -46,21 +46,6 @@ ENUM_VALUE_LIST OFF,ON
|
|||
READ_ONLY YES
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
GLOBAL_VALUE_PATH NULL
|
||||
VARIABLE_NAME DEBUG_NO_THREAD_ALARM
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE OFF
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE OFF
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BOOLEAN
|
||||
VARIABLE_COMMENT Disable system thread alarm calls. Disabling it may be useful in debugging or testing, never do it in production
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE NULL
|
||||
NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY YES
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
GLOBAL_VALUE_PATH NULL
|
||||
VARIABLE_NAME DEBUG_SYNC
|
||||
SESSION_VALUE ON - current signals: ''
|
||||
GLOBAL_VALUE NULL
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# bool readonly
|
||||
|
||||
#
|
||||
# show values;
|
||||
#
|
||||
select @@global.debug_no_thread_alarm;
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
select @@session.debug_no_thread_alarm;
|
||||
show global variables like 'debug_no_thread_alarm';
|
||||
show session variables like 'debug_no_thread_alarm';
|
||||
select * from information_schema.global_variables where variable_name='debug_no_thread_alarm';
|
||||
select * from information_schema.session_variables where variable_name='debug_no_thread_alarm';
|
||||
|
||||
#
|
||||
# show that it's read-only
|
||||
#
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
set global debug_no_thread_alarm=1;
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
set session debug_no_thread_alarm=1;
|
||||
|
|
@ -34,7 +34,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c my_default.c
|
|||
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c
|
||||
my_basename.c
|
||||
my_write.c ptr_cmp.c queues.c stacktrace.c
|
||||
string.c thr_alarm.c thr_lock.c thr_mutex.c
|
||||
string.c thr_lock.c thr_mutex.c
|
||||
thr_rwlock.c thr_timer.c
|
||||
tree.c typelib.c base64.c my_memmem.c
|
||||
my_getpagesize.c
|
||||
|
|
|
@ -468,7 +468,7 @@ PSI_mutex_key key_LOCK_localtime_r;
|
|||
|
||||
PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
|
||||
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock,
|
||||
key_LOCK_alarm, key_LOCK_timer,
|
||||
key_LOCK_timer,
|
||||
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
|
||||
key_THR_LOCK_lock, key_THR_LOCK_malloc,
|
||||
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
|
||||
|
@ -487,7 +487,6 @@ static PSI_mutex_info all_mysys_mutexes[]=
|
|||
{ &key_IO_CACHE_append_buffer_lock, "IO_CACHE::append_buffer_lock", 0},
|
||||
{ &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0},
|
||||
{ &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0},
|
||||
{ &key_LOCK_alarm, "LOCK_alarm", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_timer, "LOCK_timer", PSI_FLAG_GLOBAL},
|
||||
{ &key_my_thread_var_mutex, "my_thread_var::mutex", 0},
|
||||
{ &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL},
|
||||
|
@ -504,13 +503,12 @@ static PSI_mutex_info all_mysys_mutexes[]=
|
|||
{ &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL }
|
||||
};
|
||||
|
||||
PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond,
|
||||
PSI_cond_key key_COND_timer, key_IO_CACHE_SHARE_cond,
|
||||
key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend,
|
||||
key_THR_COND_threads, key_WT_RESOURCE_cond;
|
||||
|
||||
static PSI_cond_info all_mysys_conds[]=
|
||||
{
|
||||
{ &key_COND_alarm, "COND_alarm", PSI_FLAG_GLOBAL},
|
||||
{ &key_COND_timer, "COND_timer", PSI_FLAG_GLOBAL},
|
||||
{ &key_IO_CACHE_SHARE_cond, "IO_CACHE_SHARE::cond", 0},
|
||||
{ &key_IO_CACHE_SHARE_cond_writer, "IO_CACHE_SHARE::cond_writer", 0},
|
||||
|
@ -526,16 +524,10 @@ static PSI_rwlock_info all_mysys_rwlocks[]=
|
|||
{ &key_SAFEHASH_mutex, "SAFE_HASH::mutex", 0}
|
||||
};
|
||||
|
||||
#ifdef USE_ALARM_THREAD
|
||||
PSI_thread_key key_thread_alarm;
|
||||
#endif
|
||||
PSI_thread_key key_thread_timer;
|
||||
|
||||
static PSI_thread_info all_mysys_threads[]=
|
||||
{
|
||||
#ifdef USE_ALARM_THREAD
|
||||
{ &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL},
|
||||
#endif
|
||||
{ &key_thread_timer, "statement_timer", PSI_FLAG_GLOBAL}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "mysys_priv.h"
|
||||
#include <signal.h>
|
||||
#include <m_string.h>
|
||||
#include <thr_alarm.h>
|
||||
#include <my_pthread.h>
|
||||
|
||||
#if (defined(__BSD__) || defined(_BSDI_VERSION))
|
||||
|
@ -234,11 +233,7 @@ void *sigwait_thread(void *set_arg)
|
|||
sigaction(i, &sact, (struct sigaction*) 0);
|
||||
}
|
||||
}
|
||||
/* Ensure that init_thr_alarm() is called */
|
||||
DBUG_ASSERT(thr_client_alarm);
|
||||
sigaddset(set, thr_client_alarm);
|
||||
pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0);
|
||||
alarm_thread=pthread_self(); /* For thr_alarm */
|
||||
|
||||
for (;;)
|
||||
{ /* Wait for signals */
|
||||
|
|
|
@ -43,20 +43,17 @@ extern PSI_mutex_key key_LOCK_localtime_r;
|
|||
#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */
|
||||
|
||||
extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
|
||||
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm,
|
||||
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock,
|
||||
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
|
||||
key_THR_LOCK_lock, key_THR_LOCK_malloc,
|
||||
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
|
||||
key_THR_LOCK_open, key_THR_LOCK_threads, key_LOCK_uuid_generator,
|
||||
key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_timer;
|
||||
|
||||
extern PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond,
|
||||
extern PSI_cond_key key_COND_timer, key_IO_CACHE_SHARE_cond,
|
||||
key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend,
|
||||
key_THR_COND_threads;
|
||||
|
||||
#ifdef USE_ALARM_THREAD
|
||||
extern PSI_thread_key key_thread_alarm;
|
||||
#endif /* USE_ALARM_THREAD */
|
||||
extern PSI_thread_key key_thread_timer;
|
||||
extern PSI_rwlock_key key_SAFEHASH_mutex;
|
||||
|
||||
|
|
|
@ -1,845 +0,0 @@
|
|||
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates
|
||||
Copyright (c) 2012, 2014, SkySQL 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; version 2 of the License.
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
/* To avoid problems with alarms in debug code, we disable DBUG here */
|
||||
#define FORCE_DBUG_OFF
|
||||
#include "mysys_priv.h"
|
||||
#include <my_global.h>
|
||||
|
||||
#if !defined(DONT_USE_THR_ALARM)
|
||||
#include <errno.h>
|
||||
#include <my_pthread.h>
|
||||
#include <signal.h>
|
||||
#include <my_sys.h>
|
||||
#include <m_string.h>
|
||||
#include <queues.h>
|
||||
#include "thr_alarm.h"
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h> /* AIX needs this for fd_set */
|
||||
#endif
|
||||
|
||||
#ifndef ETIME
|
||||
#define ETIME ETIMEDOUT
|
||||
#endif
|
||||
|
||||
#ifdef DBUG_OFF
|
||||
#define reset_index_in_queue(alarm_data)
|
||||
#else
|
||||
#define reset_index_in_queue(alarm_data) alarm_data->index_in_queue= 0;
|
||||
#endif /* DBUG_OFF */
|
||||
|
||||
#ifndef USE_ONE_SIGNAL_HAND
|
||||
#define one_signal_hand_sigmask(A,B,C) pthread_sigmask((A), (B), (C))
|
||||
#else
|
||||
#define one_signal_hand_sigmask(A,B,C)
|
||||
#endif
|
||||
|
||||
my_bool thr_alarm_inited= 0, my_disable_thr_alarm= 0;
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
uint thr_client_alarm;
|
||||
static int alarm_aborted=1; /* No alarm thread */
|
||||
volatile my_bool alarm_thread_running= 0;
|
||||
time_t next_alarm_expire_time= ~ (time_t) 0;
|
||||
static sig_handler process_alarm_part2(int sig);
|
||||
|
||||
static mysql_mutex_t LOCK_alarm;
|
||||
static mysql_cond_t COND_alarm;
|
||||
static sigset_t full_signal_set;
|
||||
static QUEUE alarm_queue;
|
||||
static uint max_used_alarms=0;
|
||||
pthread_t alarm_thread;
|
||||
|
||||
#define MY_THR_ALARM_QUEUE_EXTENT 10
|
||||
|
||||
#ifdef USE_ALARM_THREAD
|
||||
static void *alarm_handler(void *arg);
|
||||
#define reschedule_alarms() mysql_cond_signal(&COND_alarm)
|
||||
#else
|
||||
#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM)
|
||||
#endif
|
||||
|
||||
static sig_handler thread_alarm(int sig __attribute__((unused)));
|
||||
|
||||
static int compare_ulong(void *not_used __attribute__((unused)),
|
||||
uchar *a_ptr,uchar* b_ptr)
|
||||
{
|
||||
ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr);
|
||||
return (a < b) ? -1 : (a == b) ? 0 : 1;
|
||||
}
|
||||
|
||||
void init_thr_alarm(uint max_alarms)
|
||||
{
|
||||
sigset_t s;
|
||||
DBUG_ENTER("init_thr_alarm");
|
||||
alarm_aborted=0;
|
||||
next_alarm_expire_time= ~ (time_t) 0;
|
||||
init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0,
|
||||
compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1,
|
||||
MY_THR_ALARM_QUEUE_EXTENT);
|
||||
sigfillset(&full_signal_set); /* Neaded to block signals */
|
||||
mysql_mutex_init(key_LOCK_alarm, &LOCK_alarm, MY_MUTEX_INIT_FAST);
|
||||
mysql_cond_init(key_COND_alarm, &COND_alarm, NULL);
|
||||
thr_client_alarm= SIGUSR1;
|
||||
my_sigset(thr_client_alarm, thread_alarm);
|
||||
sigemptyset(&s);
|
||||
sigaddset(&s, THR_SERVER_ALARM);
|
||||
alarm_thread=pthread_self();
|
||||
#if defined(USE_ALARM_THREAD)
|
||||
{
|
||||
pthread_attr_t thr_attr;
|
||||
pthread_attr_init(&thr_attr);
|
||||
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
|
||||
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
||||
mysql_thread_create(key_thread_alarm,
|
||||
&alarm_thread, &thr_attr, alarm_handler, NULL);
|
||||
pthread_attr_destroy(&thr_attr);
|
||||
}
|
||||
#elif defined(USE_ONE_SIGNAL_HAND)
|
||||
pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */
|
||||
#else
|
||||
my_sigset(THR_SERVER_ALARM, process_alarm);
|
||||
pthread_sigmask(SIG_UNBLOCK, &s, NULL);
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void resize_thr_alarm(uint max_alarms)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
/*
|
||||
It's ok not to shrink the queue as there may be more pending alarms than
|
||||
than max_alarms
|
||||
*/
|
||||
if (alarm_queue.elements < max_alarms)
|
||||
{
|
||||
resize_queue(&alarm_queue,max_alarms+1);
|
||||
max_used_alarms= alarm_queue.elements;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Request alarm after sec seconds.
|
||||
|
||||
SYNOPSIS
|
||||
thr_alarm()
|
||||
alrm Pointer to alarm detection
|
||||
alarm_data Structure to store in alarm queue
|
||||
|
||||
NOTES
|
||||
This function can't be called from the alarm-handling thread.
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 If no more alarms are allowed (aborted by process)
|
||||
|
||||
Stores in first argument a pointer to a non-zero int which is set to 0
|
||||
when the alarm has been given
|
||||
*/
|
||||
|
||||
my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
||||
{
|
||||
time_t now, next;
|
||||
#ifndef USE_ONE_SIGNAL_HAND
|
||||
sigset_t old_mask;
|
||||
#endif
|
||||
my_bool reschedule;
|
||||
struct st_my_thread_var *current_my_thread_var= my_thread_var;
|
||||
DBUG_ENTER("thr_alarm");
|
||||
DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec));
|
||||
|
||||
if (my_disable_thr_alarm)
|
||||
{
|
||||
(*alrm)= &alarm_data->alarmed;
|
||||
alarm_data->alarmed= 1; /* Abort if interrupted */
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if (unlikely(alarm_aborted))
|
||||
{ /* No signal thread */
|
||||
DBUG_PRINT("info", ("alarm aborted"));
|
||||
if (alarm_aborted > 0)
|
||||
goto abort_no_unlock;
|
||||
sec= 1; /* Abort mode */
|
||||
}
|
||||
|
||||
now= my_time(0);
|
||||
if (!alarm_data)
|
||||
{
|
||||
if (!(alarm_data=(ALARM*) my_malloc(PSI_INSTRUMENT_ME, sizeof(ALARM),
|
||||
MYF(MY_WME))))
|
||||
goto abort_no_unlock;
|
||||
alarm_data->malloced= 1;
|
||||
}
|
||||
else
|
||||
alarm_data->malloced= 0;
|
||||
next= now + sec;
|
||||
alarm_data->expire_time= next;
|
||||
alarm_data->alarmed= 0;
|
||||
alarm_data->thread= current_my_thread_var->pthread_self;
|
||||
alarm_data->thread_id= current_my_thread_var->id;
|
||||
|
||||
one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
||||
mysql_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
|
||||
if (alarm_queue.elements >= max_used_alarms)
|
||||
{
|
||||
max_used_alarms=alarm_queue.elements+1;
|
||||
}
|
||||
reschedule= (ulong) next_alarm_expire_time > (ulong) next;
|
||||
queue_insert_safe(&alarm_queue, (uchar*) alarm_data);
|
||||
assert(alarm_data->index_in_queue > 0);
|
||||
|
||||
/* Reschedule alarm if the current one has more than sec left */
|
||||
if (unlikely(reschedule))
|
||||
{
|
||||
DBUG_PRINT("info", ("reschedule"));
|
||||
if (pthread_equal(pthread_self(),alarm_thread))
|
||||
{
|
||||
alarm(sec); /* purecov: inspected */
|
||||
next_alarm_expire_time= next;
|
||||
}
|
||||
else
|
||||
reschedule_alarms(); /* Reschedule alarms */
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||
(*alrm)= &alarm_data->alarmed;
|
||||
DBUG_RETURN(0);
|
||||
|
||||
abort_no_unlock:
|
||||
*alrm= 0; /* No alarm */
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Remove alarm from list of alarms
|
||||
*/
|
||||
|
||||
void thr_end_alarm(thr_alarm_t *alarmed)
|
||||
{
|
||||
ALARM *alarm_data;
|
||||
#ifndef USE_ONE_SIGNAL_HAND
|
||||
sigset_t old_mask;
|
||||
#endif
|
||||
DBUG_ENTER("thr_end_alarm");
|
||||
|
||||
if (my_disable_thr_alarm)
|
||||
DBUG_VOID_RETURN;
|
||||
one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
||||
alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
DBUG_ASSERT(alarm_data->index_in_queue != 0);
|
||||
DBUG_ASSERT((ALARM*) queue_element(&alarm_queue,
|
||||
alarm_data->index_in_queue) ==
|
||||
alarm_data);
|
||||
queue_remove(&alarm_queue, alarm_data->index_in_queue);
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||
reset_index_in_queue(alarm_data);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Come here when some alarm in queue is due.
|
||||
Mark all alarms with are finnished in list.
|
||||
Schedule alarms to be sent again after 1-10 sec (many alarms at once)
|
||||
If alarm_aborted is set then all alarms are given and resent
|
||||
every second.
|
||||
*/
|
||||
|
||||
sig_handler process_alarm(int sig __attribute__((unused)))
|
||||
{
|
||||
sigset_t old_mask;
|
||||
/*
|
||||
This must be first as we can't call DBUG inside an alarm for a normal thread
|
||||
*/
|
||||
|
||||
/*
|
||||
We have to do do the handling of the alarm in a sub function,
|
||||
because otherwise we would get problems with two threads calling
|
||||
DBUG_... functions at the same time (as two threads may call
|
||||
process_alarm() at the same time
|
||||
*/
|
||||
|
||||
#ifndef USE_ALARM_THREAD
|
||||
pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask);
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
#endif
|
||||
process_alarm_part2(sig);
|
||||
#ifndef USE_ALARM_THREAD
|
||||
#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND)
|
||||
my_sigset(THR_SERVER_ALARM,process_alarm);
|
||||
#endif
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static sig_handler process_alarm_part2(int sig __attribute__((unused)))
|
||||
{
|
||||
ALARM *alarm_data;
|
||||
DBUG_ENTER("process_alarm");
|
||||
DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements));
|
||||
|
||||
#if defined(MAIN) && !defined(__bsdi__)
|
||||
printf("process_alarm\n"); fflush(stdout);
|
||||
#endif
|
||||
if (likely(alarm_queue.elements))
|
||||
{
|
||||
if (unlikely(alarm_aborted))
|
||||
{
|
||||
uint i;
|
||||
for (i= queue_first_element(&alarm_queue) ;
|
||||
i <= queue_last_element(&alarm_queue) ;)
|
||||
{
|
||||
alarm_data=(ALARM*) queue_element(&alarm_queue,i);
|
||||
alarm_data->alarmed=1; /* Info to thread */
|
||||
if (pthread_equal(alarm_data->thread,alarm_thread) ||
|
||||
pthread_kill(alarm_data->thread, thr_client_alarm))
|
||||
{
|
||||
#ifdef MAIN
|
||||
printf("Warning: pthread_kill couldn't find thread!!!\n");
|
||||
#endif
|
||||
queue_remove(&alarm_queue,i); /* No thread. Remove alarm */
|
||||
reset_index_in_queue(alarm_data);
|
||||
}
|
||||
else
|
||||
i++; /* Signal next thread */
|
||||
}
|
||||
#ifndef USE_ALARM_THREAD
|
||||
if (alarm_queue.elements)
|
||||
alarm(1); /* Signal soon again */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t now= my_time(0);
|
||||
time_t next= now+10-(now%10);
|
||||
while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
|
||||
{
|
||||
alarm_data->alarmed=1; /* Info to thread */
|
||||
DBUG_PRINT("info",("sending signal to waiting thread"));
|
||||
if (pthread_equal(alarm_data->thread,alarm_thread) ||
|
||||
pthread_kill(alarm_data->thread, thr_client_alarm))
|
||||
{
|
||||
#ifdef MAIN
|
||||
printf("Warning: pthread_kill couldn't find thread!!!\n");
|
||||
#endif /* MAIN */
|
||||
queue_remove_top(&alarm_queue); /* No thread. Remove alarm */
|
||||
reset_index_in_queue(alarm_data);
|
||||
if (!alarm_queue.elements)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm_data->expire_time=next;
|
||||
queue_replace_top(&alarm_queue);
|
||||
}
|
||||
}
|
||||
#ifndef USE_ALARM_THREAD
|
||||
if (alarm_queue.elements)
|
||||
{
|
||||
#ifdef __bsdi__
|
||||
alarm(0); /* Remove old alarm */
|
||||
#endif
|
||||
alarm((uint) (alarm_data->expire_time-now));
|
||||
next_alarm_expire_time= alarm_data->expire_time;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Ensure that next time we call thr_alarm(), we will schedule a new alarm
|
||||
*/
|
||||
next_alarm_expire_time= ~(time_t) 0;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Schedule all alarms now and optionally free all structures
|
||||
|
||||
SYNPOSIS
|
||||
end_thr_alarm()
|
||||
free_structures Set to 1 if we should free memory used for
|
||||
the alarm queue.
|
||||
When we call this we should KNOW that there
|
||||
is no active alarms
|
||||
IMPLEMENTATION
|
||||
Set alarm_abort to -1 which will change the behavior of alarms as follows:
|
||||
- All old alarms will be rescheduled at once
|
||||
- All new alarms will be rescheduled to one second
|
||||
*/
|
||||
|
||||
void end_thr_alarm(my_bool free_structures)
|
||||
{
|
||||
DBUG_ENTER("end_thr_alarm");
|
||||
if (alarm_aborted != 1) /* If memory not freed */
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
DBUG_PRINT("info",("Rescheduling %d waiting alarms",alarm_queue.elements));
|
||||
alarm_aborted= -1; /* mark aborted */
|
||||
if (alarm_queue.elements || (alarm_thread_running && free_structures))
|
||||
{
|
||||
if (pthread_equal(pthread_self(),alarm_thread))
|
||||
alarm(1); /* Shut down everything soon */
|
||||
else
|
||||
reschedule_alarms();
|
||||
}
|
||||
if (free_structures)
|
||||
{
|
||||
struct timespec abstime;
|
||||
|
||||
DBUG_ASSERT(!alarm_queue.elements);
|
||||
|
||||
/* Wait until alarm thread dies */
|
||||
set_timespec(abstime, 10); /* Wait up to 10 seconds */
|
||||
while (alarm_thread_running)
|
||||
{
|
||||
int error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
|
||||
if (error == ETIME || error == ETIMEDOUT)
|
||||
break; /* Don't wait forever */
|
||||
}
|
||||
delete_queue(&alarm_queue);
|
||||
alarm_aborted= 1;
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
if (!alarm_thread_running) /* Safety */
|
||||
{
|
||||
mysql_mutex_destroy(&LOCK_alarm);
|
||||
mysql_cond_destroy(&COND_alarm);
|
||||
}
|
||||
}
|
||||
else
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Remove another thread from the alarm
|
||||
*/
|
||||
|
||||
void thr_alarm_kill(my_thread_id thread_id)
|
||||
{
|
||||
uint i;
|
||||
DBUG_ENTER("thr_alarm_kill");
|
||||
|
||||
if (alarm_aborted)
|
||||
return;
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
for (i= queue_first_element(&alarm_queue) ;
|
||||
i <= queue_last_element(&alarm_queue);
|
||||
i++)
|
||||
{
|
||||
ALARM *element= (ALARM*) queue_element(&alarm_queue,i);
|
||||
if (element->thread_id == thread_id)
|
||||
{
|
||||
DBUG_PRINT("info", ("found thread; Killing it"));
|
||||
element->expire_time= 0;
|
||||
queue_replace(&alarm_queue, i);
|
||||
reschedule_alarms();
|
||||
break;
|
||||
}
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void thr_alarm_info(ALARM_INFO *info)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
info->next_alarm_time= 0;
|
||||
info->max_used_alarms= max_used_alarms;
|
||||
if ((info->active_alarms= alarm_queue.elements))
|
||||
{
|
||||
time_t now= my_time(0);
|
||||
long time_diff;
|
||||
ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
|
||||
time_diff= (long) (alarm_data->expire_time - now);
|
||||
info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff);
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
}
|
||||
|
||||
/*
|
||||
This is here for thread to get interruptet from read/write/fcntl
|
||||
ARGSUSED
|
||||
*/
|
||||
|
||||
|
||||
static sig_handler thread_alarm(int sig __attribute__((unused)))
|
||||
{
|
||||
#ifdef MAIN
|
||||
printf("thread_alarm\n"); fflush(stdout);
|
||||
#endif
|
||||
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
|
||||
my_sigset(sig,thread_alarm); /* int. thread system calls */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_TIMESPEC_TS_SEC
|
||||
#define tv_sec ts_sec
|
||||
#define tv_nsec ts_nsec
|
||||
#endif
|
||||
|
||||
/* set up a alarm thread with uses 'sleep' to sleep between alarms */
|
||||
|
||||
#ifdef USE_ALARM_THREAD
|
||||
static void *alarm_handler(void *arg __attribute__((unused)))
|
||||
{
|
||||
int error;
|
||||
struct timespec abstime;
|
||||
#ifdef MAIN
|
||||
puts("Starting alarm thread");
|
||||
#endif
|
||||
my_thread_init();
|
||||
alarm_thread_running= 1;
|
||||
mysql_mutex_lock(&LOCK_alarm);
|
||||
for (;;)
|
||||
{
|
||||
if (alarm_queue.elements)
|
||||
{
|
||||
time_t sleep_time,now= my_time(0);
|
||||
if (alarm_aborted)
|
||||
sleep_time=now+1;
|
||||
else
|
||||
sleep_time= ((ALARM*) queue_top(&alarm_queue))->expire_time;
|
||||
if (sleep_time > now)
|
||||
{
|
||||
abstime.tv_sec=sleep_time;
|
||||
abstime.tv_nsec=0;
|
||||
next_alarm_expire_time= sleep_time;
|
||||
if ((error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime)) &&
|
||||
error != ETIME && error != ETIMEDOUT)
|
||||
{
|
||||
#ifdef MAIN
|
||||
printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n",
|
||||
error,errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (alarm_aborted == -1)
|
||||
break;
|
||||
else
|
||||
{
|
||||
next_alarm_expire_time= ~ (time_t) 0;
|
||||
if ((error= mysql_cond_wait(&COND_alarm, &LOCK_alarm)))
|
||||
{
|
||||
#ifdef MAIN
|
||||
printf("Got error: %d from ptread_cond_wait (errno: %d)\n",
|
||||
error,errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
process_alarm(0);
|
||||
}
|
||||
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
|
||||
alarm_thread_running= 0;
|
||||
mysql_cond_signal(&COND_alarm);
|
||||
mysql_mutex_unlock(&LOCK_alarm);
|
||||
pthread_exit(0);
|
||||
return 0; /* Impossible */
|
||||
}
|
||||
#endif /* USE_ALARM_THREAD */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Handling of test case (when compiled with -DMAIN)
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef MAIN
|
||||
#if !defined(DONT_USE_THR_ALARM)
|
||||
|
||||
static mysql_cond_t COND_thread_count;
|
||||
static mysql_mutex_t LOCK_thread_count;
|
||||
static uint thread_count;
|
||||
|
||||
#ifdef HPUX10
|
||||
typedef int * fd_set_ptr;
|
||||
#else
|
||||
typedef fd_set * fd_set_ptr;
|
||||
#endif /* HPUX10 */
|
||||
|
||||
static void *test_thread(void *arg)
|
||||
{
|
||||
int i,param=*((int*) arg),wait_time,retry;
|
||||
time_t start_time;
|
||||
thr_alarm_t got_alarm;
|
||||
fd_set fd;
|
||||
FD_ZERO(&fd);
|
||||
my_thread_init();
|
||||
printf("Thread %d (%s) started\n",param,my_thread_name()); fflush(stdout);
|
||||
for (i=1 ; i <= 10 ; i++)
|
||||
{
|
||||
wait_time=param ? 11-i : i;
|
||||
start_time= my_time(0);
|
||||
if (thr_alarm(&got_alarm,wait_time,0))
|
||||
{
|
||||
printf("Thread: %s Alarms aborted\n",my_thread_name());
|
||||
break;
|
||||
}
|
||||
if (wait_time == 3)
|
||||
{
|
||||
printf("Thread: %s Simulation of no alarm needed\n",my_thread_name());
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (retry=0 ; !thr_got_alarm(&got_alarm) && retry < 10 ; retry++)
|
||||
{
|
||||
printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time);
|
||||
select(0,(fd_set_ptr) &fd,0,0,0);
|
||||
}
|
||||
if (!thr_got_alarm(&got_alarm))
|
||||
{
|
||||
printf("Thread: %s didn't get an alarm. Aborting!\n",
|
||||
my_thread_name());
|
||||
break;
|
||||
}
|
||||
if (wait_time == 7)
|
||||
{ /* Simulate alarm-miss */
|
||||
fd_set readFDs;
|
||||
uint max_connection=fileno(stdin);
|
||||
FD_ZERO(&readFDs);
|
||||
FD_SET(max_connection,&readFDs);
|
||||
retry=0;
|
||||
for (;;)
|
||||
{
|
||||
printf("Thread: %s Simulating alarm miss\n",my_thread_name());
|
||||
fflush(stdout);
|
||||
if (select(max_connection+1, (fd_set_ptr) &readFDs,0,0,0) < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
break; /* Got new interrupt */
|
||||
printf("Got errno: %d from select. Retrying..\n",errno);
|
||||
if (retry++ >= 3)
|
||||
{
|
||||
printf("Warning: Interrupt of select() doesn't set errno!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* This shouldn't happen */
|
||||
{
|
||||
if (!FD_ISSET(max_connection,&readFDs))
|
||||
{
|
||||
printf("Select interrupted, but errno not set\n");
|
||||
fflush(stdout);
|
||||
if (retry++ >= 3)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
(void) getchar(); /* Somebody was playing */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(),
|
||||
(int) (my_time(0)-start_time), wait_time); fflush(stdout);
|
||||
thr_end_alarm(&got_alarm);
|
||||
fflush(stdout);
|
||||
}
|
||||
mysql_mutex_lock(&LOCK_thread_count);
|
||||
thread_count--;
|
||||
mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
my_thread_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void *signal_hand(void *arg __attribute__((unused)))
|
||||
{
|
||||
sigset_t set;
|
||||
int sig,error,err_count=0;;
|
||||
|
||||
my_thread_init();
|
||||
pthread_detach_this_thread();
|
||||
init_thr_alarm(10); /* Setup alarm handler */
|
||||
mysql_mutex_lock(&LOCK_thread_count); /* Required by bsdi */
|
||||
mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
|
||||
sigemptyset(&set); /* Catch all signals */
|
||||
sigaddset(&set,SIGINT);
|
||||
sigaddset(&set,SIGQUIT);
|
||||
sigaddset(&set,SIGTERM);
|
||||
sigaddset(&set,SIGHUP);
|
||||
#ifdef SIGTSTP
|
||||
sigaddset(&set,SIGTSTP);
|
||||
#endif
|
||||
#ifdef USE_ONE_SIGNAL_HAND
|
||||
sigaddset(&set,THR_SERVER_ALARM); /* For alarms */
|
||||
puts("Starting signal and alarm handling thread");
|
||||
#else
|
||||
puts("Starting signal handling thread");
|
||||
#endif
|
||||
printf("server alarm: %d thread alarm: %d\n",
|
||||
THR_SERVER_ALARM, thr_client_alarm);
|
||||
DBUG_PRINT("info",("Starting signal and alarm handling thread"));
|
||||
for(;;)
|
||||
{
|
||||
int code;
|
||||
while ((error=my_sigwait(&set,&sig,&code)) == EINTR)
|
||||
printf("sigwait restarted\n");
|
||||
if (error)
|
||||
{
|
||||
fprintf(stderr,"Got error %d from sigwait\n",error);
|
||||
if (err_count++ > 5)
|
||||
exit(1); /* Too many errors in test */
|
||||
continue;
|
||||
}
|
||||
#ifdef USE_ONE_SIGNAL_HAND
|
||||
if (sig != THR_SERVER_ALARM)
|
||||
#endif
|
||||
printf("Main thread: Got signal %d\n",sig);
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
printf("Aborting nicely\n");
|
||||
end_thr_alarm(0);
|
||||
break;
|
||||
#ifdef SIGTSTP
|
||||
case SIGTSTP:
|
||||
printf("Aborting\n");
|
||||
exit(1);
|
||||
return 0; /* Keep some compilers happy */
|
||||
#endif
|
||||
#ifdef USE_ONE_SIGNAL_HAND
|
||||
case THR_SERVER_ALARM:
|
||||
process_alarm(sig);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
|
||||
{
|
||||
pthread_t tid;
|
||||
pthread_attr_t thr_attr;
|
||||
int i, param[2], error;
|
||||
sigset_t set;
|
||||
ALARM_INFO alarm_info;
|
||||
MY_INIT(argv[0]);
|
||||
|
||||
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
|
||||
{
|
||||
DBUG_PUSH(argv[1]+2);
|
||||
}
|
||||
mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
|
||||
mysql_cond_init(0, &COND_thread_count, NULL);
|
||||
|
||||
/* Start a alarm handling thread */
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set,SIGINT);
|
||||
sigaddset(&set,SIGQUIT);
|
||||
sigaddset(&set,SIGTERM);
|
||||
sigaddset(&set,SIGHUP);
|
||||
signal(SIGTERM,SIG_DFL); /* If it's blocked by parent */
|
||||
#ifdef SIGTSTP
|
||||
sigaddset(&set,SIGTSTP);
|
||||
#endif
|
||||
sigaddset(&set,THR_SERVER_ALARM);
|
||||
sigdelset(&set, thr_client_alarm);
|
||||
(void) pthread_sigmask(SIG_SETMASK,&set,NULL);
|
||||
|
||||
pthread_attr_init(&thr_attr);
|
||||
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
|
||||
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
||||
pthread_attr_setstacksize(&thr_attr,65536L);
|
||||
|
||||
/* Start signal thread and wait for it to start */
|
||||
mysql_mutex_lock(&LOCK_thread_count);
|
||||
mysql_thread_create(0, &tid, &thr_attr, signal_hand, NULL);
|
||||
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
DBUG_PRINT("info",("signal thread created"));
|
||||
|
||||
thr_setconcurrency(3);
|
||||
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
|
||||
printf("Main thread: %s\n",my_thread_name());
|
||||
for (i=0 ; i < 2 ; i++)
|
||||
{
|
||||
param[i]= i;
|
||||
mysql_mutex_lock(&LOCK_thread_count);
|
||||
if ((error= mysql_thread_create(0,
|
||||
&tid, &thr_attr, test_thread,
|
||||
(void*) ¶m[i])))
|
||||
{
|
||||
printf("Can't create thread %d, error: %d\n",i,error);
|
||||
exit(1);
|
||||
}
|
||||
thread_count++;
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&thr_attr);
|
||||
mysql_mutex_lock(&LOCK_thread_count);
|
||||
thr_alarm_info(&alarm_info);
|
||||
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
|
||||
alarm_info.active_alarms, alarm_info.max_used_alarms,
|
||||
alarm_info.next_alarm_time);
|
||||
while (thread_count)
|
||||
{
|
||||
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
|
||||
if (thread_count == 1)
|
||||
{
|
||||
printf("Calling end_thr_alarm. This should cancel the last thread\n");
|
||||
end_thr_alarm(0);
|
||||
}
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
thr_alarm_info(&alarm_info);
|
||||
end_thr_alarm(1);
|
||||
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
|
||||
alarm_info.active_alarms, alarm_info.max_used_alarms,
|
||||
alarm_info.next_alarm_time);
|
||||
printf("Test succeeded\n");
|
||||
mysql_cond_destroy(&COND_thread_count);
|
||||
mysql_mutex_destroy(&LOCK_thread_count);
|
||||
my_end(MY_CHECK_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !defined(DONT_USE_ALARM_THREAD) */
|
||||
|
||||
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
|
||||
{
|
||||
printf("thr_alarm disabled with DONT_USE_THR_ALARM\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif /* !defined(DONT_USE_ALARM_THREAD) */
|
||||
#endif /* WIN */
|
||||
#endif /* MAIN */
|
|
@ -20,7 +20,6 @@
|
|||
#error You have already included an client_settings.h and it should not be included twice
|
||||
#endif /* CLIENT_SETTINGS_INCLUDED */
|
||||
|
||||
#include <thr_alarm.h>
|
||||
#include <sql_common.h>
|
||||
|
||||
/*
|
||||
|
|
|
@ -113,7 +113,6 @@
|
|||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include <thr_alarm.h>
|
||||
#include <ft_global.h>
|
||||
#include <errmsg.h>
|
||||
#include "sp_rcontext.h"
|
||||
|
@ -1670,10 +1669,11 @@ static void break_connect_loop()
|
|||
int UNINIT_VAR(error);
|
||||
DBUG_PRINT("info",("Waiting for select thread"));
|
||||
|
||||
#ifndef DONT_USE_THR_ALARM
|
||||
if (pthread_kill(select_thread, thr_client_alarm))
|
||||
break; // allready dead
|
||||
#endif
|
||||
for(size_t i=0; i < listen_sockets.size(); i++)
|
||||
{
|
||||
int fd=mysql_socket_getfd(listen_sockets.at(i));
|
||||
shutdown(fd, SHUT_RDWR);
|
||||
}
|
||||
set_timespec(abstime, 2);
|
||||
for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
|
||||
{
|
||||
|
@ -1765,8 +1765,6 @@ static void close_connections(void)
|
|||
listen_sockets.free_memory();
|
||||
mysql_mutex_unlock(&LOCK_start_thread);
|
||||
|
||||
end_thr_alarm(0); // Abort old alarms.
|
||||
|
||||
while (CONNECT::count)
|
||||
my_sleep(100);
|
||||
|
||||
|
@ -1877,10 +1875,6 @@ extern "C" sig_handler print_signal_warning(int sig)
|
|||
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
|
||||
my_sigset(sig,print_signal_warning); /* int. thread system calls */
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
if (sig == SIGALRM)
|
||||
alarm(2); /* reschedule alarm */
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -2027,7 +2021,6 @@ static void clean_up(bool print_message)
|
|||
multi_keycache_free();
|
||||
sp_cache_end();
|
||||
free_status_vars();
|
||||
end_thr_alarm(1); /* Free allocated memory */
|
||||
end_thr_timer();
|
||||
my_free_open_file_info();
|
||||
if (defaults_argv)
|
||||
|
@ -3110,8 +3103,6 @@ void init_signals(void)
|
|||
struct sigaction sa;
|
||||
DBUG_ENTER("init_signals");
|
||||
|
||||
my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
|
||||
|
||||
if (opt_stack_trace || (test_flags & TEST_CORE_ON_SIGNAL))
|
||||
{
|
||||
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
|
||||
|
@ -3159,7 +3150,6 @@ void init_signals(void)
|
|||
sa.sa_flags = 0;
|
||||
sa.sa_handler = print_signal_warning;
|
||||
sigaction(SIGHUP, &sa, (struct sigaction*) 0);
|
||||
sigaddset(&set,THR_SERVER_ALARM);
|
||||
if (test_flags & TEST_SIGINT)
|
||||
{
|
||||
/* Allow SIGINT to break mysqld. This is for debugging with --gdb */
|
||||
|
@ -3220,7 +3210,7 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
|
|||
#endif
|
||||
|
||||
|
||||
/** This threads handles all signals and alarms. */
|
||||
/** This threads handles all signals */
|
||||
/* ARGSUSED */
|
||||
pthread_handler_t signal_hand(void *arg __attribute__((unused)))
|
||||
{
|
||||
|
@ -3230,13 +3220,6 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
|
|||
DBUG_ENTER("signal_hand");
|
||||
signal_thread_in_use= 1;
|
||||
|
||||
/*
|
||||
Setup alarm handler
|
||||
This should actually be '+ max_number_of_slaves' instead of +10,
|
||||
but the +10 should be quite safe.
|
||||
*/
|
||||
init_thr_alarm(thread_scheduler->max_threads + extra_max_connections +
|
||||
global_system_variables.max_insert_delayed_threads + 10);
|
||||
if (test_flags & TEST_SIGINT)
|
||||
{
|
||||
/* Allow SIGINT to break mysqld. This is for debugging with --gdb */
|
||||
|
@ -3245,9 +3228,6 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
|
|||
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
|
||||
}
|
||||
(void) sigemptyset(&set); // Setup up SIGINT for debug
|
||||
#ifdef USE_ONE_SIGNAL_HAND
|
||||
(void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
|
||||
#endif
|
||||
#ifndef IGNORE_SIGHUP_SIGQUIT
|
||||
(void) sigaddset(&set,SIGQUIT);
|
||||
(void) sigaddset(&set,SIGHUP);
|
||||
|
@ -3311,7 +3291,7 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
|
|||
error);
|
||||
#else
|
||||
my_sigset(sig, SIG_IGN);
|
||||
break_connect_loop(); // MIT THREAD has a alarm thread
|
||||
break_connect_loop();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -3341,11 +3321,6 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
|
|||
opt_log ? fixed_log_output_options : LOG_NONE);
|
||||
}
|
||||
break;
|
||||
#ifdef USE_ONE_SIGNAL_HAND
|
||||
case THR_SERVER_ALARM:
|
||||
process_alarm(sig); // Trigger alarms.
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
#ifdef EXTRA_DEBUG
|
||||
sql_print_warning("Got signal: %d error: %d",sig,error); /* purecov: tested */
|
||||
|
@ -5854,7 +5829,7 @@ int mysqld_main(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
/*
|
||||
init signals & alarm
|
||||
init signals
|
||||
After this we can't quit by a simple unireg_abort
|
||||
*/
|
||||
start_signal_handler(); // Creates pidfile
|
||||
|
|
510
sql/net_serv.cc
510
sql/net_serv.cc
|
@ -47,6 +47,8 @@
|
|||
#include "probes_mysql.h"
|
||||
#include <debug_sync.h>
|
||||
#include "proxy_protocol.h"
|
||||
#include <mysql_com_server.h>
|
||||
#include <mysqld.h>
|
||||
|
||||
PSI_memory_key key_memory_NET_buff;
|
||||
PSI_memory_key key_memory_NET_compress_packet;
|
||||
|
@ -62,13 +64,9 @@ PSI_memory_key key_memory_NET_compress_packet;
|
|||
*/
|
||||
#ifdef EXTRA_DEBUG
|
||||
#define EXTRA_DEBUG_fprintf fprintf
|
||||
#define EXTRA_DEBUG_fflush fflush
|
||||
#define EXTRA_DEBUG_ASSERT DBUG_ASSERT
|
||||
#else
|
||||
static void inline EXTRA_DEBUG_fprintf(...) {}
|
||||
#ifndef MYSQL_SERVER
|
||||
static int inline EXTRA_DEBUG_fflush(...) { return 0; }
|
||||
#endif
|
||||
#endif /* EXTRA_DEBUG */
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
|
@ -92,22 +90,6 @@ static void inline MYSQL_SERVER_my_error(...) {}
|
|||
the client should have a bigger max_allowed_packet.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) || !defined(MYSQL_SERVER)
|
||||
/* The following is because alarms doesn't work on windows. */
|
||||
#ifndef NO_ALARM
|
||||
#define NO_ALARM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_ALARM
|
||||
#include "my_pthread.h"
|
||||
void sql_print_error(const char *format,...);
|
||||
#else
|
||||
#define DONT_USE_THR_ALARM
|
||||
#endif /* NO_ALARM */
|
||||
|
||||
#include "thr_alarm.h"
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
/*
|
||||
The following variables/functions should really not be declared
|
||||
|
@ -158,22 +140,18 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags)
|
|||
net->last_errno=0;
|
||||
net->thread_specific_malloc= MY_TEST(my_flags & MY_THREAD_SPECIFIC);
|
||||
net->thd= 0;
|
||||
#ifdef MYSQL_SERVER
|
||||
net->extension= NULL;
|
||||
net->thd= thd;
|
||||
#endif
|
||||
|
||||
if (vio)
|
||||
{
|
||||
/* For perl DBI/DBD. */
|
||||
net->fd= vio_fd(vio);
|
||||
#if defined(MYSQL_SERVER) && !defined(_WIN32)
|
||||
if (!(test_flags & TEST_BLOCKING))
|
||||
{
|
||||
my_bool old_mode;
|
||||
vio_blocking(vio, FALSE, &old_mode);
|
||||
}
|
||||
#endif
|
||||
vio_fastsend(vio);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
@ -646,12 +624,7 @@ net_real_write(NET *net,const uchar *packet, size_t len)
|
|||
{
|
||||
size_t length;
|
||||
const uchar *pos,*end;
|
||||
thr_alarm_t alarmed;
|
||||
#ifndef NO_ALARM
|
||||
ALARM alarm_buff;
|
||||
#endif
|
||||
uint retry_count=0;
|
||||
my_bool net_blocking = vio_is_blocking(net->vio);
|
||||
DBUG_ENTER("net_real_write");
|
||||
|
||||
#if defined(MYSQL_SERVER)
|
||||
|
@ -707,62 +680,21 @@ net_real_write(NET *net,const uchar *packet, size_t len)
|
|||
#ifdef DEBUG_DATA_PACKETS
|
||||
DBUG_DUMP("data_written", packet, len);
|
||||
#endif
|
||||
|
||||
#ifndef NO_ALARM
|
||||
thr_alarm_init(&alarmed);
|
||||
if (net_blocking)
|
||||
thr_alarm(&alarmed, net->write_timeout, &alarm_buff);
|
||||
#else
|
||||
alarmed=0;
|
||||
/* Write timeout is set in my_net_set_write_timeout */
|
||||
#endif /* NO_ALARM */
|
||||
|
||||
pos= packet;
|
||||
end=pos+len;
|
||||
while (pos != end)
|
||||
{
|
||||
if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
|
||||
length= vio_write(net->vio, pos, (size_t) (end - pos));
|
||||
if (ssize_t(length) <= 0)
|
||||
{
|
||||
my_bool interrupted = vio_should_retry(net->vio);
|
||||
#if !defined(_WIN32)
|
||||
if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
|
||||
bool interrupted= vio_should_retry(net->vio);
|
||||
if (interrupted || !length)
|
||||
{
|
||||
if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff))
|
||||
{ /* Always true for client */
|
||||
my_bool old_mode;
|
||||
while (vio_blocking(net->vio, TRUE, &old_mode) < 0)
|
||||
{
|
||||
if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
|
||||
continue;
|
||||
EXTRA_DEBUG_fprintf(stderr,
|
||||
"%s: my_net_write: fcntl returned error %d, aborting thread\n",
|
||||
my_progname,vio_errno(net->vio));
|
||||
net->error= 2; /* Close socket */
|
||||
net->last_errno= ER_NET_PACKET_TOO_LARGE;
|
||||
MYSQL_SERVER_my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
retry_count=0;
|
||||
continue;
|
||||
}
|
||||
if (retry_count++ < net->retry_count)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif /* !defined(_WIN32) */
|
||||
if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
|
||||
interrupted)
|
||||
{
|
||||
if (retry_count++ < net->retry_count)
|
||||
continue;
|
||||
EXTRA_DEBUG_fprintf(stderr, "%s: write looped, aborting thread\n",
|
||||
my_progname);
|
||||
}
|
||||
#ifndef MYSQL_SERVER
|
||||
if (vio_errno(net->vio) == SOCKET_EINTR)
|
||||
{
|
||||
DBUG_PRINT("warning",("Interrupted write. Retrying..."));
|
||||
continue;
|
||||
}
|
||||
#endif /* !defined(MYSQL_SERVER) */
|
||||
EXTRA_DEBUG_fprintf(stderr, "%s: write looped, aborting thread\n",
|
||||
my_progname);
|
||||
net->error= 2; /* Close socket */
|
||||
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
|
||||
ER_NET_ERROR_ON_WRITE);
|
||||
|
@ -772,112 +704,14 @@ net_real_write(NET *net,const uchar *packet, size_t len)
|
|||
pos+=length;
|
||||
update_statistics(thd_increment_bytes_sent(net->thd, length));
|
||||
}
|
||||
#ifndef _WIN32
|
||||
end:
|
||||
#endif
|
||||
#ifdef HAVE_COMPRESS
|
||||
if (net->compress)
|
||||
my_free((void*) packet);
|
||||
#endif
|
||||
if (thr_alarm_in_use(&alarmed))
|
||||
{
|
||||
my_bool old_mode;
|
||||
thr_end_alarm(&alarmed);
|
||||
if (!net_blocking)
|
||||
vio_blocking(net->vio, net_blocking, &old_mode);
|
||||
}
|
||||
net->reading_or_writing=0;
|
||||
DBUG_RETURN(((int) (pos != end)));
|
||||
net->reading_or_writing= 0;
|
||||
DBUG_RETURN(pos != end);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Read something from server/clinet
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NO_ALARM
|
||||
|
||||
static my_bool net_safe_read(NET *net, uchar *buff, size_t length,
|
||||
thr_alarm_t *alarmed)
|
||||
{
|
||||
uint retry_count=0;
|
||||
while (length > 0)
|
||||
{
|
||||
size_t tmp;
|
||||
if ((long) (tmp= vio_read(net->vio, buff, length)) <= 0)
|
||||
{
|
||||
my_bool interrupted = vio_should_retry(net->vio);
|
||||
if (!thr_got_alarm(alarmed) && interrupted)
|
||||
{ /* Probably in MIT threads */
|
||||
if (retry_count++ < net->retry_count)
|
||||
continue;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
length-= tmp;
|
||||
buff+= tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Help function to clear the commuication buffer when we get a too big packet.
|
||||
|
||||
@param net Communication handle
|
||||
@param remain Bytes to read
|
||||
@param alarmed Parameter for thr_alarm()
|
||||
@param alarm_buff Parameter for thr_alarm()
|
||||
|
||||
@retval
|
||||
0 Was able to read the whole packet
|
||||
@retval
|
||||
1 Got mailformed packet from client
|
||||
*/
|
||||
|
||||
static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
|
||||
ALARM *alarm_buff)
|
||||
{
|
||||
longlong limit= net->max_packet_size*net->net_skip_rest_factor;
|
||||
uint32 old=remain;
|
||||
DBUG_ENTER("my_net_skip_rest");
|
||||
DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
|
||||
|
||||
/* The following is good for debugging */
|
||||
update_statistics(thd_increment_net_big_packet_count(net->thd, 1));
|
||||
|
||||
if (!thr_alarm_in_use(alarmed))
|
||||
{
|
||||
my_bool old_mode;
|
||||
if (thr_alarm(alarmed,net->read_timeout, alarm_buff) ||
|
||||
vio_blocking(net->vio, TRUE, &old_mode) < 0)
|
||||
DBUG_RETURN(1); /* Can't setup, abort */
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
while (remain > 0)
|
||||
{
|
||||
size_t length= MY_MIN(remain, net->max_packet);
|
||||
if (net_safe_read(net, net->buff, length, alarmed))
|
||||
DBUG_RETURN(1);
|
||||
update_statistics(thd_increment_bytes_received(net->thd, length));
|
||||
remain -= (uint32) length;
|
||||
limit-= length;
|
||||
if (limit < 0)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (old != MAX_PACKET_LENGTH)
|
||||
break;
|
||||
if (net_safe_read(net, net->buff, NET_HEADER_SIZE, alarmed))
|
||||
DBUG_RETURN(1);
|
||||
limit-= NET_HEADER_SIZE;
|
||||
old=remain= uint3korr(net->buff);
|
||||
net->pkt_nr++;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#endif /* NO_ALARM */
|
||||
|
||||
|
||||
/**
|
||||
Try to parse and process proxy protocol header.
|
||||
|
||||
|
@ -951,26 +785,17 @@ static handle_proxy_header_result handle_proxy_header(NET *net)
|
|||
Returns length of packet.
|
||||
*/
|
||||
|
||||
static ulong
|
||||
my_real_read(NET *net, size_t *complen,
|
||||
my_bool header __attribute__((unused)))
|
||||
static ulong my_real_read(NET *net, size_t *complen,
|
||||
my_bool header __attribute__((unused)))
|
||||
{
|
||||
uchar *pos;
|
||||
size_t length;
|
||||
uint i,retry_count=0;
|
||||
ulong len=packet_error;
|
||||
my_bool expect_error_packet __attribute__((unused))= 0;
|
||||
thr_alarm_t alarmed;
|
||||
#ifndef NO_ALARM
|
||||
ALARM alarm_buff;
|
||||
#endif
|
||||
|
||||
retry:
|
||||
|
||||
my_bool net_blocking=vio_is_blocking(net->vio);
|
||||
uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
|
||||
NET_HEADER_SIZE);
|
||||
#ifdef MYSQL_SERVER
|
||||
size_t count= remain;
|
||||
struct st_net_server *server_extension= 0;
|
||||
|
||||
|
@ -983,254 +808,143 @@ retry:
|
|||
server_extension->m_before_header(net, user_data, count);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*complen = 0;
|
||||
|
||||
net->reading_or_writing=1;
|
||||
thr_alarm_init(&alarmed);
|
||||
#ifndef NO_ALARM
|
||||
if (net_blocking)
|
||||
thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
|
||||
#else
|
||||
/* Read timeout is set in my_net_set_read_timeout */
|
||||
#endif /* NO_ALARM */
|
||||
|
||||
pos = net->buff + net->where_b; /* net->packet -4 */
|
||||
for (i=0 ; i < 2 ; i++)
|
||||
pos = net->buff + net->where_b;
|
||||
for (i=0; i < 2 ; i++)
|
||||
{
|
||||
while (remain > 0)
|
||||
{
|
||||
while (remain > 0)
|
||||
length= vio_read(net->vio, pos, remain);
|
||||
if ((ssize_t) length <= 0)
|
||||
{
|
||||
/* First read is done with non blocking mode */
|
||||
if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
|
||||
DBUG_PRINT("info", ("vio_read returned %lld errno: %d",
|
||||
(long long) length, vio_errno(net->vio)));
|
||||
if (i == 0 && unlikely(thd_net_is_killed((THD *) net->thd)))
|
||||
{
|
||||
my_bool interrupted = vio_should_retry(net->vio);
|
||||
|
||||
DBUG_PRINT("info",("vio_read returned %ld errno: %d",
|
||||
(long) length, vio_errno(net->vio)));
|
||||
|
||||
if (i== 0 && unlikely(thd_net_is_killed((THD*) net->thd)))
|
||||
{
|
||||
DBUG_PRINT("info", ("thd is killed"));
|
||||
len= packet_error;
|
||||
net->error= 0;
|
||||
net->last_errno= ER_CONNECTION_KILLED;
|
||||
MYSQL_SERVER_my_error(net->last_errno, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && defined(MYSQL_SERVER)
|
||||
/*
|
||||
We got an error that there was no data on the socket. We now set up
|
||||
an alarm to not 'read forever', change the socket to the blocking
|
||||
mode and try again
|
||||
*/
|
||||
if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
|
||||
{
|
||||
if (!thr_alarm(&alarmed,net->read_timeout,&alarm_buff)) /* Don't wait too long */
|
||||
{
|
||||
my_bool old_mode;
|
||||
while (vio_blocking(net->vio, TRUE, &old_mode) < 0)
|
||||
{
|
||||
if (vio_should_retry(net->vio) &&
|
||||
retry_count++ < net->retry_count)
|
||||
continue;
|
||||
DBUG_PRINT("error",
|
||||
("fcntl returned error %d, aborting thread",
|
||||
vio_errno(net->vio)));
|
||||
EXTRA_DEBUG_fprintf(stderr,
|
||||
"%s: read: fcntl returned error %d, aborting thread\n",
|
||||
my_progname,vio_errno(net->vio));
|
||||
len= packet_error;
|
||||
net->error= 2; /* Close socket */
|
||||
net->last_errno= ER_NET_FCNTL_ERROR;
|
||||
MYSQL_SERVER_my_error(ER_NET_FCNTL_ERROR, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
retry_count=0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif /* (!defined(_WIN32) && defined(MYSQL_SERVER) */
|
||||
if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
|
||||
interrupted)
|
||||
{ /* Probably in MIT threads */
|
||||
if (retry_count++ < net->retry_count)
|
||||
continue;
|
||||
EXTRA_DEBUG_fprintf(stderr, "%s: read looped with error %d, aborting thread\n",
|
||||
my_progname,vio_errno(net->vio));
|
||||
}
|
||||
#ifndef MYSQL_SERVER
|
||||
if (length != 0 && vio_errno(net->vio) == SOCKET_EINTR)
|
||||
{
|
||||
DBUG_PRINT("warning",("Interrupted read. Retrying..."));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld",
|
||||
remain, vio_errno(net->vio), (long) length));
|
||||
len= packet_error;
|
||||
net->error= 2; /* Close socket */
|
||||
net->last_errno= (vio_was_timeout(net->vio) ?
|
||||
ER_NET_READ_INTERRUPTED :
|
||||
ER_NET_READ_ERROR);
|
||||
DBUG_PRINT("info", ("thd is killed"));
|
||||
len= packet_error;
|
||||
net->error= 0;
|
||||
net->last_errno= ER_CONNECTION_KILLED;
|
||||
MYSQL_SERVER_my_error(net->last_errno, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
remain -= (uint32) length;
|
||||
pos+= length;
|
||||
update_statistics(thd_increment_bytes_received(net->thd, length));
|
||||
goto end;
|
||||
}
|
||||
if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
|
||||
continue;
|
||||
EXTRA_DEBUG_fprintf(stderr,
|
||||
"%s: read looped with error %d, aborting thread\n",
|
||||
my_progname, vio_errno(net->vio));
|
||||
DBUG_PRINT("error",
|
||||
("Couldn't read packet: remain: %u errno: %d length: %ld",
|
||||
remain, vio_errno(net->vio), (long) length));
|
||||
len= packet_error;
|
||||
net->error= 2;
|
||||
net->last_errno= (vio_was_timeout(net->vio) ? ER_NET_READ_INTERRUPTED
|
||||
: ER_NET_READ_ERROR);
|
||||
MYSQL_SERVER_my_error(net->last_errno, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
|
||||
remain-= (uint32) length;
|
||||
pos+= length;
|
||||
update_statistics(thd_increment_bytes_received(net->thd, length));
|
||||
}
|
||||
#ifdef DEBUG_DATA_PACKETS
|
||||
DBUG_DUMP("data_read", net->buff+net->where_b, length);
|
||||
DBUG_DUMP("data_read", net->buff + net->where_b, length);
|
||||
#endif
|
||||
if (i == 0)
|
||||
{ /* First parts is packet length */
|
||||
size_t helping;
|
||||
if (i == 0)
|
||||
{
|
||||
/* First part is packet length */
|
||||
size_t helping;
|
||||
#ifndef DEBUG_DATA_PACKETS
|
||||
DBUG_DUMP("packet_header", net->buff+net->where_b,
|
||||
NET_HEADER_SIZE);
|
||||
#endif
|
||||
if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
|
||||
{
|
||||
#ifndef MYSQL_SERVER
|
||||
if (net->buff[net->where_b + 3] == (uchar) (net->pkt_nr -1))
|
||||
{
|
||||
/*
|
||||
If the server was killed then the server may have missed the
|
||||
last sent client packet and the packet numbering may be one off.
|
||||
*/
|
||||
DBUG_PRINT("warning", ("Found possible out of order packets"));
|
||||
expect_error_packet= 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
goto packets_out_of_order;
|
||||
}
|
||||
net->compress_pkt_nr= ++net->pkt_nr;
|
||||
#ifdef HAVE_COMPRESS
|
||||
if (net->compress)
|
||||
{
|
||||
/*
|
||||
The following uint3korr() may read 4 bytes, so make sure we don't
|
||||
read unallocated or uninitialized memory. The right-hand expression
|
||||
must match the size of the buffer allocated in net_realloc().
|
||||
*/
|
||||
DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
|
||||
net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1);
|
||||
/*
|
||||
If the packet is compressed then complen > 0 and contains the
|
||||
number of bytes in the uncompressed packet
|
||||
*/
|
||||
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
|
||||
}
|
||||
#endif
|
||||
|
||||
len=uint3korr(net->buff+net->where_b);
|
||||
if (!len) /* End of big multi-packet */
|
||||
goto end;
|
||||
helping = MY_MAX(len,*complen) + net->where_b;
|
||||
/* The necessary size of net->buff */
|
||||
if (helping >= net->max_packet)
|
||||
{
|
||||
if (net_realloc(net,helping))
|
||||
{
|
||||
#if defined(MYSQL_SERVER) && !defined(NO_ALARM)
|
||||
if (!net->compress &&
|
||||
!my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff))
|
||||
net->error= 3; /* Successfully skiped packet */
|
||||
#endif
|
||||
len= packet_error; /* Return error and close connection */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
pos=net->buff + net->where_b;
|
||||
remain = (uint32) len;
|
||||
#ifdef MYSQL_SERVER
|
||||
if (server_extension != NULL)
|
||||
{
|
||||
void *user_data= server_extension->m_user_data;
|
||||
server_extension->m_after_header(net, user_data, count, 0);
|
||||
server_extension= NULL;
|
||||
}
|
||||
DBUG_DUMP("packet_header", net->buff + net->where_b, NET_HEADER_SIZE);
|
||||
#endif
|
||||
if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
|
||||
{
|
||||
goto packets_out_of_order;
|
||||
}
|
||||
#ifndef MYSQL_SERVER
|
||||
else if (expect_error_packet)
|
||||
net->compress_pkt_nr= ++net->pkt_nr;
|
||||
#ifdef HAVE_COMPRESS
|
||||
if (net->compress)
|
||||
{
|
||||
/*
|
||||
This check is safe both for compressed and not compressed protocol
|
||||
as for the compressed protocol errors are not compressed anymore.
|
||||
The following uint3korr() may read 4 bytes, so make sure we don't
|
||||
read unallocated or uninitialized memory. The right-hand expression
|
||||
must match the size of the buffer allocated in net_realloc().
|
||||
*/
|
||||
if (net->buff[net->where_b] != (uchar) 255)
|
||||
{
|
||||
/* Restore pkt_nr to original value */
|
||||
net->pkt_nr--;
|
||||
goto packets_out_of_order;
|
||||
}
|
||||
DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
|
||||
net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1);
|
||||
/*
|
||||
If the packet is compressed then complen > 0 and contains the
|
||||
number of bytes in the uncompressed packet
|
||||
*/
|
||||
*complen= uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
|
||||
}
|
||||
#endif
|
||||
|
||||
len= uint3korr(net->buff + net->where_b);
|
||||
if (!len) /* End of big multi-packet */
|
||||
goto end;
|
||||
helping= MY_MAX(len, *complen) + net->where_b;
|
||||
/* The necessary size of net->buff */
|
||||
if (helping >= net->max_packet)
|
||||
{
|
||||
if (net_realloc(net, helping))
|
||||
{
|
||||
len= packet_error; /* Return error and close connection */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
pos= net->buff + net->where_b;
|
||||
remain= (uint32) len;
|
||||
if (server_extension != NULL)
|
||||
{
|
||||
void *user_data= server_extension->m_user_data;
|
||||
server_extension->m_after_header(net, user_data, count, 0);
|
||||
server_extension= NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (thr_alarm_in_use(&alarmed))
|
||||
{
|
||||
my_bool old_mode;
|
||||
thr_end_alarm(&alarmed);
|
||||
if (!net_blocking)
|
||||
vio_blocking(net->vio, net_blocking, &old_mode);
|
||||
}
|
||||
net->reading_or_writing=0;
|
||||
#ifdef DEBUG_DATA_PACKETS
|
||||
if (len != packet_error)
|
||||
DBUG_DUMP("data_read", net->buff+net->where_b, len);
|
||||
#endif
|
||||
#ifdef MYSQL_SERVER
|
||||
if (server_extension != NULL)
|
||||
{
|
||||
void *user_data= server_extension->m_user_data;
|
||||
server_extension->m_after_header(net, user_data, count, 1);
|
||||
DBUG_ASSERT(len == packet_error || len == 0);
|
||||
}
|
||||
#endif
|
||||
return(len);
|
||||
|
||||
packets_out_of_order:
|
||||
packets_out_of_order :
|
||||
switch (handle_proxy_header(net))
|
||||
{
|
||||
switch (handle_proxy_header(net)) {
|
||||
case ABORT:
|
||||
/* error happened, message is already written. */
|
||||
len= packet_error;
|
||||
goto end;
|
||||
case RETRY:
|
||||
goto retry;
|
||||
case IGNORE:
|
||||
break;
|
||||
}
|
||||
|
||||
DBUG_PRINT("error",
|
||||
("Packets out of order (Found: %d, expected %u)",
|
||||
(int) net->buff[net->where_b + 3],
|
||||
net->pkt_nr));
|
||||
EXTRA_DEBUG_ASSERT(0);
|
||||
/*
|
||||
We don't make noise server side, since the client is expected
|
||||
to break the protocol for e.g. --send LOAD DATA .. LOCAL where
|
||||
the server expects the client to send a file, but the client
|
||||
may reply with a new command instead.
|
||||
*/
|
||||
#ifndef MYSQL_SERVER
|
||||
EXTRA_DEBUG_fflush(stdout);
|
||||
EXTRA_DEBUG_fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n",
|
||||
(int) net->buff[net->where_b + 3],
|
||||
(uint) (uchar) net->pkt_nr);
|
||||
EXTRA_DEBUG_fflush(stderr);
|
||||
#endif
|
||||
case ABORT:
|
||||
/* error happened, message is already written. */
|
||||
len= packet_error;
|
||||
MYSQL_SERVER_my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
|
||||
goto end;
|
||||
case RETRY:
|
||||
goto retry;
|
||||
case IGNORE:
|
||||
break;
|
||||
}
|
||||
DBUG_PRINT("error", ("Packets out of order (Found: %d, expected %u)",
|
||||
(int) net->buff[net->where_b + 3], net->pkt_nr));
|
||||
EXTRA_DEBUG_ASSERT(0);
|
||||
/*
|
||||
We don't make noise server side, since the client is expected
|
||||
to break the protocol for e.g. --send LOAD DATA .. LOCAL where
|
||||
the server expects the client to send a file, but the client
|
||||
may reply with a new command instead.
|
||||
*/
|
||||
len= packet_error;
|
||||
MYSQL_SERVER_my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
|
|
14
sql/slave.cc
14
sql/slave.cc
|
@ -36,7 +36,6 @@
|
|||
#include "rpl_filter.h"
|
||||
#include "repl_failsafe.h"
|
||||
#include "transaction.h"
|
||||
#include <thr_alarm.h>
|
||||
#include <my_dir.h>
|
||||
#include <sql_common.h>
|
||||
#include <errmsg.h>
|
||||
|
@ -1075,24 +1074,11 @@ terminate_slave_thread(THD *thd,
|
|||
|
||||
mysql_mutex_lock(&thd->LOCK_thd_kill);
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
#ifndef DONT_USE_THR_ALARM
|
||||
/*
|
||||
Error codes from pthread_kill are:
|
||||
EINVAL: invalid signal number (can't happen)
|
||||
ESRCH: thread already killed (can happen, should be ignored)
|
||||
*/
|
||||
int err __attribute__((unused))= pthread_kill(thd->real_id, thr_client_alarm);
|
||||
DBUG_ASSERT(err != EINVAL);
|
||||
#endif
|
||||
thd->awake_no_mutex(NOT_KILLED);
|
||||
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_kill);
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
|
||||
/*
|
||||
There is a small chance that slave thread might miss the first
|
||||
alarm. To protect againts it, resend the signal until it reacts
|
||||
*/
|
||||
struct timespec abstime;
|
||||
set_timespec(abstime,2);
|
||||
error= mysql_cond_timedwait(term_cond, term_lock, &abstime);
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "sql_audit.h"
|
||||
#include <m_ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <thr_alarm.h>
|
||||
#include <mysys_err.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
@ -1903,9 +1902,6 @@ void THD::awake_no_mutex(killed_state state_to_set)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Mark the target thread's alarm request expired, and signal alarm. */
|
||||
thr_alarm_kill(thread_id);
|
||||
|
||||
/* Send an event to the scheduler that a thread should be killed. */
|
||||
if (!slave_thread)
|
||||
MYSQL_CALLBACK(scheduler, post_kill_notification, (this));
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "keycaches.h"
|
||||
#include "my_json_writer.h"
|
||||
#include <hash.h>
|
||||
#include <thr_alarm.h>
|
||||
#include "sql_connect.h"
|
||||
#include "thread_cache.h"
|
||||
#if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H)
|
||||
|
@ -611,17 +610,6 @@ Open streams: %10lu\n",
|
|||
my_file_opened,
|
||||
my_stream_opened);
|
||||
|
||||
#ifndef DONT_USE_THR_ALARM
|
||||
ALARM_INFO alarm_info;
|
||||
thr_alarm_info(&alarm_info);
|
||||
printf("\nAlarm status:\n\
|
||||
Active alarms: %u\n\
|
||||
Max used alarms: %u\n\
|
||||
Next alarm time: %lu\n",
|
||||
alarm_info.active_alarms,
|
||||
alarm_info.max_used_alarms,
|
||||
(ulong)alarm_info.next_alarm_time);
|
||||
#endif
|
||||
display_table_locks();
|
||||
#if defined(HAVE_MALLINFO2)
|
||||
struct mallinfo2 info = mallinfo2();
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "my_sys.h"
|
||||
|
||||
#include "events.h"
|
||||
#include <thr_alarm.h>
|
||||
#include "slave.h"
|
||||
#include "rpl_mi.h"
|
||||
#include "rpl_filter.h"
|
||||
|
@ -1735,10 +1734,6 @@ Sys_max_binlog_size(
|
|||
|
||||
static bool fix_max_connections(sys_var *self, THD *thd, enum_var_type type)
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
resize_thr_alarm(max_connections + extra_max_connections +
|
||||
global_system_variables.max_insert_delayed_threads + 10);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6753,13 +6748,6 @@ static Sys_var_enum Sys_histogram_type(
|
|||
SESSION_VAR(histogram_type), CMD_LINE(REQUIRED_ARG),
|
||||
histogram_types, DEFAULT(2));
|
||||
|
||||
static Sys_var_mybool Sys_no_thread_alarm(
|
||||
"debug_no_thread_alarm",
|
||||
"Disable system thread alarm calls. Disabling it may be useful "
|
||||
"in debugging or testing, never do it in production",
|
||||
READ_ONLY GLOBAL_VAR(my_disable_thr_alarm), CMD_LINE(OPT_ARG),
|
||||
DEFAULT(FALSE));
|
||||
|
||||
static Sys_var_mybool Sys_query_cache_strip_comments(
|
||||
"query_cache_strip_comments",
|
||||
"Strip all comments from a query before storing it "
|
||||
|
|
Loading…
Reference in a new issue