Commit e1e83a8b authored by unknown's avatar unknown

BUG#25712 - insert delayed and check table run together report crashed

            tables

In case system doesn't have native pread/pwrite calls (e.g. Windows)
and there is CHECK TABLE runs concurrently with another statement that
reads from a table, the table may be reported as crashed.

This is fixed by locking file descriptor when my_seek is executed on
MyISAM index file and emulated pread/pwrite may be executed concurrently.

Affects MyISAM tables on platforms that do not have native
pread/pwrite calls (e.g. Windows).

No deterministic test case for this bug.


myisam/mi_check.c:
  Key file descriptor is shared among threads and mixed set of
  my_pread/my_pwrite and my_seek calls is possible. This is not
  a problem on systems that have native pread/pwrite calls.
  
  In case system doesn't have native pread/pwrite calls (e.g. Windows)
  we must ensure that my_pread/my_pwrite are not executed at the same
  time with my_seek. This is done by passing MY_THREADSAFE flag to
  my_seek.
mysys/my_seek.c:
  On platforms that do not have native pread/pwrite calls (e.g. Windows)
  these calls are emulated as follow: lock fd, lseek, read, unlock fd.
  
  In case file descriptor is shared among threads, where one thread
  executes my_pread and another thread executes my_seek, we may read
  from a wrong position. This may happen because my_seek doesn't lock
  fd and thus may be executed by another thread after emulated pread
  has done lseek and before it has done read.
  
  To fix problem mentioned above we introduce new flag MY_THREADSAFE to
  my_seek, which is meaningful only in case pread/pwrite calls are
  emulated. If this flag is set, lseek operation is performed as follow:
  lock fd, seek, unlock fd.
parent 0eaf9739
......@@ -336,7 +336,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
flush_key_blocks(info->s->key_cache,
info->s->kfile, FLUSH_FORCE_WRITE);
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size)
{
if (skr > size)
......@@ -595,7 +595,8 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
{
/* purecov: begin tested */
/* Give it a chance to fit in the real file size. */
my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(0));
my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
MYF(MY_THREADSAFE));
mi_check_print_error(param, "Invalid key block position: %s "
"key block size: %u file_length: %s",
llstr(page, llbuff), keyinfo->block_length,
......@@ -4039,10 +4040,10 @@ int test_if_almost_full(MI_INFO *info)
{
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
return 0;
return (my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0))/10*9 >
(my_off_t) (info->s->base.max_key_file_length) ||
my_seek(info->dfile,0L,MY_SEEK_END,MYF(0))/10*9 >
(my_off_t) info->s->base.max_data_file_length);
return my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)) / 10 * 9 >
(my_off_t) info->s->base.max_key_file_length ||
my_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
(my_off_t) info->s->base.max_data_file_length;
}
/* Recreate table with bigger more alloced record-data */
......
......@@ -24,7 +24,9 @@
my_off_t pos The expected position (absolute or relative)
int whence A direction parameter and one of
{SEEK_SET, SEEK_CUR, SEEK_END}
myf MyFlags Not used.
myf MyFlags MY_THREADSAFE must be set in case my_seek may be mixed
with my_pread/my_pwrite calls and fd is shared among
threads.
DESCRIPTION
The my_seek function is a wrapper around the system call lseek and
......@@ -51,7 +53,16 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
whence, MyFlags));
DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
newpos=lseek(fd, pos, whence);
#if defined(THREAD) && !defined(HAVE_PREAD)
if (MyFlags & MY_THREADSAFE)
{
pthread_mutex_lock(&my_file_info[fd].mutex);
newpos= lseek(fd, pos, whence);
pthread_mutex_lock(&my_file_info[fd].mutex);
}
else
#endif
newpos= lseek(fd, pos, whence);
if (newpos == (os_off_t) -1)
{
my_errno=errno;
......
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