Bug#20789 Merge Subtable Rename Causes Crash

- When a MyISAM table which belongs to a merge table union and is 
  renamed the associated file descriptors are closed on windows.
  This causes a server crash next time an insert or update is 
  performed on the merge table.
- This patch prevents the system from crashing on windows by
  checking for bad file descriptors every time the MyISAM table
  is locked by associated the merge table.
parent 441e16e8
...@@ -224,6 +224,21 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -224,6 +224,21 @@ int mi_lock_database(MI_INFO *info, int lock_type)
break; /* Impossible */ break; /* Impossible */
} }
} }
#ifdef __WIN__
else
{
/*
Check for bad file descriptors if this table is part
of a merge union. Failing to capture this may cause
a crash on windows if the table is renamed and
later on referenced by the merge table.
*/
if( info->owned_by_merge && (info->s)->kfile < 0 )
{
error = HA_ERR_NO_SUCH_TABLE;
}
}
#endif
pthread_mutex_unlock(&share->intern_lock); pthread_mutex_unlock(&share->intern_lock);
#if defined(FULL_LOG) || defined(_lint) #if defined(FULL_LOG) || defined(_lint)
lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ lock_type|=(int) (flag << 8); /* Set bit to set if real lock */
......
...@@ -278,6 +278,9 @@ struct st_myisam_info { ...@@ -278,6 +278,9 @@ struct st_myisam_info {
my_bool page_changed; /* If info->buff can't be used for rnext */ my_bool page_changed; /* If info->buff can't be used for rnext */
my_bool buff_used; /* If info->buff has to be reread for rnext */ my_bool buff_used; /* If info->buff has to be reread for rnext */
my_bool once_flags; /* For MYISAMMRG */ my_bool once_flags; /* For MYISAMMRG */
#ifdef __WIN__
my_bool owned_by_merge; /* This MyISAM table is part of a merge union */
#endif
#ifdef THREAD #ifdef THREAD
THR_LOCK_DATA lock; THR_LOCK_DATA lock;
#endif #endif
......
...@@ -27,7 +27,18 @@ int myrg_lock_database(MYRG_INFO *info, int lock_type) ...@@ -27,7 +27,18 @@ int myrg_lock_database(MYRG_INFO *info, int lock_type)
error=0; error=0;
for (file=info->open_tables ; file != info->end_table ; file++) for (file=info->open_tables ; file != info->end_table ; file++)
{
#ifdef __WIN__
/*
Make sure this table is marked as owned by a merge table.
The semaphore is never released as long as table remains
in memory. This should be refactored into a more generic
approach (observer pattern)
*/
(file->table)->owned_by_merge = TRUE;
#endif
if ((new_error=mi_lock_database(file->table,lock_type))) if ((new_error=mi_lock_database(file->table,lock_type)))
error=new_error; error=new_error;
}
return(error); return(error);
} }
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