Commit 8cadc6fd authored by Venkata Sidagam's avatar Venkata Sidagam

Bug #11752803 SERVER CRASHES IF MAX_CONNECTIONS DECREASED BELOW

               CERTAIN LEVEL
      
Problem description: mysqld crashes when we update the max_connections 
variable to lesser value than the number of currently open connections.
      
Analysis: The "alarm_queue.max_elements" size will be decided at the 
server start time and it will get modified if we change max_connections 
value. In the current scenario the value of "alarm_queue.max_elements" 
is decremented when the max_connections is set to 2. When updating the  
"alarm_queue.max_elements" value we are not updating "max_used_alarms" 
value. Hence, instead of getting the warning "thr_alarm queue is full" 
it is ending up in asserting the server at the time of inserting new 
elements in the queue.
      
Fix: the fix is to dynamically increase the size of the alarm_queue.
In order to do that, queue_insert_safe() should be used instead if
queue_insert().
parent 09e9f4d0
...@@ -52,6 +52,8 @@ static QUEUE alarm_queue; ...@@ -52,6 +52,8 @@ static QUEUE alarm_queue;
static uint max_used_alarms=0; static uint max_used_alarms=0;
pthread_t alarm_thread; pthread_t alarm_thread;
#define MY_THR_ALARM_QUEUE_EXTENT 10
#ifdef USE_ALARM_THREAD #ifdef USE_ALARM_THREAD
static void *alarm_handler(void *arg); static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm) #define reschedule_alarms() pthread_cond_signal(&COND_alarm)
...@@ -74,8 +76,8 @@ void init_thr_alarm(uint max_alarms) ...@@ -74,8 +76,8 @@ void init_thr_alarm(uint max_alarms)
DBUG_ENTER("init_thr_alarm"); DBUG_ENTER("init_thr_alarm");
alarm_aborted=0; alarm_aborted=0;
next_alarm_expire_time= ~ (time_t) 0; next_alarm_expire_time= ~ (time_t) 0;
init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, init_queue_ex(&alarm_queue, max_alarms + 1, offsetof(ALARM,expire_time), 0,
compare_ulong,NullS); compare_ulong, NullS, MY_THR_ALARM_QUEUE_EXTENT);
sigfillset(&full_signal_set); /* Neaded to block signals */ sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL); pthread_cond_init(&COND_alarm,NULL);
...@@ -127,7 +129,10 @@ void resize_thr_alarm(uint max_alarms) ...@@ -127,7 +129,10 @@ void resize_thr_alarm(uint max_alarms)
than max_alarms than max_alarms
*/ */
if (alarm_queue.elements < max_alarms) if (alarm_queue.elements < max_alarms)
{
resize_queue(&alarm_queue,max_alarms+1); resize_queue(&alarm_queue,max_alarms+1);
max_used_alarms= alarm_queue.elements;
}
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
} }
...@@ -182,17 +187,6 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) ...@@ -182,17 +187,6 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
if (alarm_queue.elements >= max_used_alarms) if (alarm_queue.elements >= max_used_alarms)
{ {
if (alarm_queue.elements == alarm_queue.max_elements)
{
DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n");
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
#ifndef USE_ONE_SIGNAL_HAND
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
#endif
DBUG_RETURN(1);
}
max_used_alarms=alarm_queue.elements+1; max_used_alarms=alarm_queue.elements+1;
} }
reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec; reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec;
...@@ -216,7 +210,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) ...@@ -216,7 +210,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
alarm_data->alarmed=0; alarm_data->alarmed=0;
alarm_data->thread= current_my_thread_var->pthread_self; alarm_data->thread= current_my_thread_var->pthread_self;
alarm_data->thread_id= current_my_thread_var->id; alarm_data->thread_id= current_my_thread_var->id;
queue_insert(&alarm_queue,(uchar*) alarm_data); queue_insert_safe(&alarm_queue, (uchar*) alarm_data);
/* Reschedule alarm if the current one has more than sec left */ /* Reschedule alarm if the current one has more than sec left */
if (reschedule) if (reschedule)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment