Commit 67496884 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug 12323643 - CLEAN UP THE INNODB THREAD SHUTDOWN AND ASSERTIONS (WL#5136)

On shutdown, do not exit threads in os_event_wait(). This method of
exiting was only used by the I/O handler threads. Exit them on a
higher level.

os_event_wait_low(), os_event_wait_time_low(): Do not exit on shutdown.

os_thread_exit(), ut_dbg_assertion_failed(), ut_print_timestamp(): Add
attribute cold, so that GCC knows that these functions are rarely
invoked and can be optimized for size.

os_aio_linux_collect(): Return on shutdown.

os_aio_linux_handle(), os_aio_simulated_handle(), os_aio_windows_handle():
Set *message1 = *message2 = NULL and return TRUE on shutdown.

fil_aio_wait(): Return on shutdown.

logs_empty_and_mark_files_at_shutdown(): Even in very fast shutdown
(innodb_fast_shutdown=2), allow the background threads to exit, but
skip the flushing and log checkpointing.

innobase_shutdown_for_mysql(): Always wait for all the threads to exit.

rb:633 approved by Sunny Bains
parent 6fe99e2d
...@@ -4527,8 +4527,8 @@ fil_aio_wait( ...@@ -4527,8 +4527,8 @@ fil_aio_wait(
ret = os_aio_linux_handle(segment, &fil_node, ret = os_aio_linux_handle(segment, &fil_node,
&message, &type); &message, &type);
#else #else
ret = 0; /* Eliminate compiler warning */
ut_error; ut_error;
ret = 0; /* Eliminate compiler warning */
#endif #endif
} else { } else {
srv_set_io_thread_op_info(segment, "simulated aio handle"); srv_set_io_thread_op_info(segment, "simulated aio handle");
...@@ -4538,6 +4538,10 @@ fil_aio_wait( ...@@ -4538,6 +4538,10 @@ fil_aio_wait(
} }
ut_a(ret); ut_a(ret);
if (UNIV_UNLIKELY(fil_node == NULL)) {
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
return;
}
srv_set_io_thread_op_info(segment, "complete io for fil node"); srv_set_io_thread_op_info(segment, "complete io for fil node");
......
...@@ -150,10 +150,7 @@ os_event_free( ...@@ -150,10 +150,7 @@ os_event_free(
os_event_t event); /*!< in: event to free */ os_event_t event); /*!< in: event to free */
/**********************************************************//** /**********************************************************//**
Waits for an event object until it is in the signaled state. If Waits for an event object until it is in the signaled state.
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state).
Typically, if the event has been signalled after the os_event_reset() Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE. we'll return immediately because event->is_set == TRUE.
......
...@@ -107,8 +107,9 @@ UNIV_INTERN ...@@ -107,8 +107,9 @@ UNIV_INTERN
void void
os_thread_exit( os_thread_exit(
/*===========*/ /*===========*/
void* exit_value); /*!< in: exit value; in Windows this void* void* exit_value) /*!< in: exit value; in Windows this void*
is cast as a DWORD */ is cast as a DWORD */
__attribute__((cold, noreturn));
/*****************************************************************//** /*****************************************************************//**
Returns the thread identifier of current thread. Returns the thread identifier of current thread.
@return current thread identifier */ @return current thread identifier */
......
...@@ -52,7 +52,8 @@ ut_dbg_assertion_failed( ...@@ -52,7 +52,8 @@ ut_dbg_assertion_failed(
/*====================*/ /*====================*/
const char* expr, /*!< in: the failed assertion */ const char* expr, /*!< in: the failed assertion */
const char* file, /*!< in: source file containing the assertion */ const char* file, /*!< in: source file containing the assertion */
ulint line); /*!< in: line number of the assertion */ ulint line) /*!< in: line number of the assertion */
__attribute__((nonnull(2), cold));
#if defined(__WIN__) || defined(__INTEL_COMPILER) #if defined(__WIN__) || defined(__INTEL_COMPILER)
# undef UT_DBG_USE_ABORT # undef UT_DBG_USE_ABORT
......
...@@ -275,7 +275,8 @@ UNIV_INTERN ...@@ -275,7 +275,8 @@ UNIV_INTERN
void void
ut_print_timestamp( ut_print_timestamp(
/*===============*/ /*===============*/
FILE* file); /*!< in: file where to print */ FILE* file) /*!< in: file where to print */
__attribute__((nonnull, cold));
/**********************************************************//** /**********************************************************//**
Sprintfs a timestamp to a buffer, 13..14 chars plus terminating NUL. */ Sprintfs a timestamp to a buffer, 13..14 chars plus terminating NUL. */
UNIV_INTERN UNIV_INTERN
......
...@@ -3078,6 +3078,7 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3078,6 +3078,7 @@ logs_empty_and_mark_files_at_shutdown(void)
{ {
ib_uint64_t lsn; ib_uint64_t lsn;
ulint arch_log_no; ulint arch_log_no;
ibool server_busy;
if (srv_print_verbose_log) { if (srv_print_verbose_log) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
...@@ -3092,14 +3093,12 @@ loop: ...@@ -3092,14 +3093,12 @@ loop:
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
/* We need the monitor threads to stop before we proceed with a /* We need the monitor threads to stop before we proceed with
normal shutdown. In case of very fast shutdown, however, we can a shutdown. */
proceed without waiting for monitor threads. */
if (srv_fast_shutdown < 2 if (srv_error_monitor_active
&& (srv_error_monitor_active
|| srv_lock_timeout_active || srv_lock_timeout_active
|| srv_monitor_active)) { || srv_monitor_active) {
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
...@@ -3114,65 +3113,57 @@ loop: ...@@ -3114,65 +3113,57 @@ loop:
for the 'very fast' shutdown, because the InnoDB layer may have for the 'very fast' shutdown, because the InnoDB layer may have
committed or prepared transactions and we don't want to lose them. */ committed or prepared transactions and we don't want to lose them. */
if (trx_n_mysql_transactions > 0 server_busy = trx_n_mysql_transactions > 0
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) { || UT_LIST_GET_LEN(trx_sys->trx_list) > 0;
mutex_exit(&kernel_mutex);
goto loop;
}
if (srv_fast_shutdown == 2) {
/* In this fastest shutdown we do not flush the buffer pool:
it is essentially a 'crash' of the InnoDB server. Make sure
that the log is all flushed to disk, so that we can recover
all committed transactions in a crash recovery. We must not
write the lsn stamps to the data files, since at a startup
InnoDB deduces from the stamps if the previous shutdown was
clean. */
log_buffer_flush_to_disk();
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
return; /* We SKIP ALL THE REST !! */ if (server_busy || srv_is_any_background_thread_active()) {
}
mutex_exit(&kernel_mutex);
/* Check that the background threads are suspended */
if (srv_is_any_background_thread_active()) {
goto loop; goto loop;
} }
mutex_enter(&(log_sys->mutex)); mutex_enter(&log_sys->mutex);
server_busy = log_sys->n_pending_checkpoint_writes
if (log_sys->n_pending_checkpoint_writes
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
|| log_sys->n_pending_archive_ios || log_sys->n_pending_archive_ios
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
|| log_sys->n_pending_writes) { || log_sys->n_pending_writes;
mutex_exit(&log_sys->mutex);
mutex_exit(&(log_sys->mutex));
if (server_busy || !buf_pool_check_no_pending_io()) {
goto loop; goto loop;
} }
mutex_exit(&(log_sys->mutex)); #ifdef UNIV_LOG_ARCHIVE
log_archive_all();
#endif /* UNIV_LOG_ARCHIVE */
if (srv_fast_shutdown == 2) {
/* In this fastest shutdown we do not flush the buffer
pool: it is essentially a 'crash' of the InnoDB
server. Make sure that the log is all flushed to disk,
so that we can recover all committed transactions in a
crash recovery. We must not write the lsn stamps to
the data files, since at a startup InnoDB deduces from
the stamps if the previous shutdown was clean. */
if (!buf_pool_check_no_pending_io()) { log_buffer_flush_to_disk();
/* Check that the background threads stay suspended */
if (srv_is_any_background_thread_active()) {
fprintf(stderr,
"InnoDB: Warning: some background thread"
" woke up during shutdown\n");
goto loop; goto loop;
} }
#ifdef UNIV_LOG_ARCHIVE srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
log_archive_all(); fil_close_all_files();
#endif /* UNIV_LOG_ARCHIVE */ ut_a(!srv_is_any_background_thread_active());
return;
}
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE); log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
mutex_enter(&(log_sys->mutex)); mutex_enter(&log_sys->mutex);
lsn = log_sys->lsn; lsn = log_sys->lsn;
...@@ -3183,7 +3174,7 @@ loop: ...@@ -3183,7 +3174,7 @@ loop:
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
) { ) {
mutex_exit(&(log_sys->mutex)); mutex_exit(&log_sys->mutex);
goto loop; goto loop;
} }
...@@ -3201,7 +3192,7 @@ loop: ...@@ -3201,7 +3192,7 @@ loop:
log_archive_close_groups(TRUE); log_archive_close_groups(TRUE);
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
mutex_exit(&(log_sys->mutex)); mutex_exit(&log_sys->mutex);
/* Check that the background threads stay suspended */ /* Check that the background threads stay suspended */
if (srv_is_any_background_thread_active()) { if (srv_is_any_background_thread_active()) {
......
...@@ -4064,13 +4064,13 @@ os_aio_func( ...@@ -4064,13 +4064,13 @@ os_aio_func(
} }
try_again: try_again:
if (mode == OS_AIO_NORMAL) { switch (mode) {
if (type == OS_FILE_READ) { case OS_AIO_NORMAL:
array = os_aio_read_array; array = (type == OS_FILE_READ)
} else { ? os_aio_read_array
array = os_aio_write_array; : os_aio_write_array;
} break;
} else if (mode == OS_AIO_IBUF) { case OS_AIO_IBUF:
ut_ad(type == OS_FILE_READ); ut_ad(type == OS_FILE_READ);
/* Reduce probability of deadlock bugs in connection with ibuf: /* Reduce probability of deadlock bugs in connection with ibuf:
do not let the ibuf i/o handler sleep */ do not let the ibuf i/o handler sleep */
...@@ -4078,19 +4078,21 @@ try_again: ...@@ -4078,19 +4078,21 @@ try_again:
wake_later = FALSE; wake_later = FALSE;
array = os_aio_ibuf_array; array = os_aio_ibuf_array;
} else if (mode == OS_AIO_LOG) { break;
case OS_AIO_LOG:
array = os_aio_log_array; array = os_aio_log_array;
} else if (mode == OS_AIO_SYNC) { break;
case OS_AIO_SYNC:
array = os_aio_sync_array; array = os_aio_sync_array;
#if defined(LINUX_NATIVE_AIO) #if defined(LINUX_NATIVE_AIO)
/* In Linux native AIO we don't use sync IO array. */ /* In Linux native AIO we don't use sync IO array. */
ut_a(!srv_use_native_aio); ut_a(!srv_use_native_aio);
#endif /* LINUX_NATIVE_AIO */ #endif /* LINUX_NATIVE_AIO */
} else { break;
array = NULL; /* Eliminate compiler warning */ default:
ut_error; ut_error;
array = NULL; /* Eliminate compiler warning */
} }
slot = os_aio_array_reserve_slot(type, array, message1, message2, file, slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
...@@ -4253,11 +4255,17 @@ os_aio_windows_handle( ...@@ -4253,11 +4255,17 @@ os_aio_windows_handle(
INFINITE); INFINITE);
} }
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { os_mutex_enter(array->mutex);
os_thread_exit(NULL);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS
&& array->n_reserved == 0) {
*message1 = NULL;
*message2 = NULL;
os_mutex_exit(array->mutex);
return(TRUE);
} }
os_mutex_enter(array->mutex); ut_a(i >= WAIT_OBJECT_0 && i <= WAIT_OBJECT_0 + n);
slot = os_aio_array_get_nth_slot(array, i + segment * n); slot = os_aio_array_get_nth_slot(array, i + segment * n);
...@@ -4403,14 +4411,6 @@ os_aio_linux_collect( ...@@ -4403,14 +4411,6 @@ os_aio_linux_collect(
retry: retry:
/* Go down if we are in shutdown mode.
In case of srv_fast_shutdown == 2, there may be pending
IO requests but that should be OK as we essentially treat
that as a crash of InnoDB. */
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
/* Initialize the events. The timeout value is arbitrary. /* Initialize the events. The timeout value is arbitrary.
We probably need to experiment with it a little. */ We probably need to experiment with it a little. */
memset(events, 0, sizeof(*events) * seg_size); memset(events, 0, sizeof(*events) * seg_size);
...@@ -4419,39 +4419,7 @@ retry: ...@@ -4419,39 +4419,7 @@ retry:
ret = io_getevents(io_ctx, 1, seg_size, events, &timeout); ret = io_getevents(io_ctx, 1, seg_size, events, &timeout);
/* This error handling is for any error in collecting the if (ret > 0) {
IO requests. The errors, if any, for any particular IO
request are simply passed on to the calling routine. */
/* Not enough resources! Try again. */
if (ret == -EAGAIN) {
goto retry;
}
/* Interrupted! I have tested the behaviour in case of an
interrupt. If we have some completed IOs available then
the return code will be the number of IOs. We get EINTR only
if there are no completed IOs and we have been interrupted. */
if (ret == -EINTR) {
goto retry;
}
/* No pending request! Go back and check again. */
if (ret == 0) {
goto retry;
}
/* All other errors! should cause a trap for now. */
if (UNIV_UNLIKELY(ret < 0)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: unexpected ret_code[%d] from"
" io_getevents()!\n", ret);
ut_error;
}
ut_a(ret > 0);
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
os_aio_slot_t* slot; os_aio_slot_t* slot;
struct iocb* control; struct iocb* control;
...@@ -4487,8 +4455,36 @@ retry: ...@@ -4487,8 +4455,36 @@ retry:
slot->io_already_done = TRUE; slot->io_already_done = TRUE;
os_mutex_exit(array->mutex); os_mutex_exit(array->mutex);
} }
return;
}
if (UNIV_UNLIKELY(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS)) {
return; return;
}
/* This error handling is for any error in collecting the
IO requests. The errors, if any, for any particular IO
request are simply passed on to the calling routine. */
switch (ret) {
case -EAGAIN:
/* Not enough resources! Try again. */
case -EINTR:
/* Interrupted! I have tested the behaviour in case of an
interrupt. If we have some completed IOs available then
the return code will be the number of IOs. We get EINTR only
if there are no completed IOs and we have been interrupted. */
case 0:
/* No pending request! Go back and check again. */
goto retry;
}
/* All other errors should cause a trap for now. */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: unexpected ret_code[%d] from io_getevents()!\n",
ret);
ut_error;
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -4532,20 +4528,35 @@ os_aio_linux_handle( ...@@ -4532,20 +4528,35 @@ os_aio_linux_handle(
/* Loop until we have found a completed request. */ /* Loop until we have found a completed request. */
for (;;) { for (;;) {
ibool any_reserved = FALSE;
os_mutex_enter(array->mutex); os_mutex_enter(array->mutex);
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
slot = os_aio_array_get_nth_slot( slot = os_aio_array_get_nth_slot(
array, i + segment * n); array, i + segment * n);
if (slot->reserved && slot->io_already_done) { if (!slot->reserved) {
continue;
} else if (slot->io_already_done) {
/* Something for us to work on. */ /* Something for us to work on. */
goto found; goto found;
} else {
any_reserved = TRUE;
} }
} }
os_mutex_exit(array->mutex); os_mutex_exit(array->mutex);
/* We don't have any completed request. /* There is no completed request.
Wait for some request. Note that we return If there is no pending request at all,
and the system is being shut down, exit. */
if (UNIV_UNLIKELY
(!any_reserved
&& srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS)) {
*message1 = NULL;
*message2 = NULL;
return(TRUE);
}
/* Wait for some request. Note that we return
from wait iff we have found a request. */ from wait iff we have found a request. */
srv_set_io_thread_op_info(global_seg, srv_set_io_thread_op_info(global_seg,
...@@ -4641,6 +4652,7 @@ os_aio_simulated_handle( ...@@ -4641,6 +4652,7 @@ os_aio_simulated_handle(
byte* combined_buf; byte* combined_buf;
byte* combined_buf2; byte* combined_buf2;
ibool ret; ibool ret;
ibool any_reserved;
ulint n; ulint n;
ulint i; ulint i;
...@@ -4671,18 +4683,21 @@ restart: ...@@ -4671,18 +4683,21 @@ restart:
goto recommended_sleep; goto recommended_sleep;
} }
os_mutex_enter(array->mutex);
srv_set_io_thread_op_info(global_segment, srv_set_io_thread_op_info(global_segment,
"looking for i/o requests (b)"); "looking for i/o requests (b)");
/* Check if there is a slot for which the i/o has already been /* Check if there is a slot for which the i/o has already been
done */ done */
any_reserved = FALSE;
os_mutex_enter(array->mutex);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
slot = os_aio_array_get_nth_slot(array, i + segment * n); slot = os_aio_array_get_nth_slot(array, i + segment * n);
if (slot->reserved && slot->io_already_done) { if (!slot->reserved) {
continue;
} else if (slot->io_already_done) {
if (os_aio_print_debug) { if (os_aio_print_debug) {
fprintf(stderr, fprintf(stderr,
...@@ -4694,7 +4709,21 @@ restart: ...@@ -4694,7 +4709,21 @@ restart:
ret = TRUE; ret = TRUE;
goto slot_io_done; goto slot_io_done;
} else {
any_reserved = TRUE;
}
} }
/* There is no completed request.
If there is no pending request at all,
and the system is being shut down, exit. */
if (UNIV_UNLIKELY
(!any_reserved
&& srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS)) {
os_mutex_exit(array->mutex);
*message1 = NULL;
*message2 = NULL;
return(TRUE);
} }
n_consecutive = 0; n_consecutive = 0;
......
...@@ -558,10 +558,7 @@ os_event_free( ...@@ -558,10 +558,7 @@ os_event_free(
} }
/**********************************************************//** /**********************************************************//**
Waits for an event object until it is in the signaled state. If Waits for an event object until it is in the signaled state.
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state).
Typically, if the event has been signalled after the os_event_reset() Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE. we'll return immediately because event->is_set == TRUE.
...@@ -586,8 +583,6 @@ os_event_wait_low( ...@@ -586,8 +583,6 @@ os_event_wait_low(
returned by previous call of returned by previous call of
os_event_reset(). */ os_event_reset(). */
{ {
ib_int64_t old_signal_count;
#ifdef __WIN__ #ifdef __WIN__
if(!srv_use_native_conditions) { if(!srv_use_native_conditions) {
DWORD err; DWORD err;
...@@ -600,43 +595,25 @@ os_event_wait_low( ...@@ -600,43 +595,25 @@ os_event_wait_low(
err = WaitForSingleObject(event->handle, INFINITE); err = WaitForSingleObject(event->handle, INFINITE);
ut_a(err == WAIT_OBJECT_0); ut_a(err == WAIT_OBJECT_0);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
return; return;
} }
#endif #endif
os_fast_mutex_lock(&(event->os_mutex)); os_fast_mutex_lock(&event->os_mutex);
if (reset_sig_count) {
old_signal_count = reset_sig_count;
} else {
old_signal_count = event->signal_count;
}
for (;;) {
if (event->is_set == TRUE
|| event->signal_count != old_signal_count) {
os_fast_mutex_unlock(&(event->os_mutex));
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL); if (!reset_sig_count) {
} reset_sig_count = event->signal_count;
/* Ok, we may return */
return;
} }
while (!event->is_set && event->signal_count == reset_sig_count) {
os_cond_wait(&(event->cond_var), &(event->os_mutex)); os_cond_wait(&(event->cond_var), &(event->os_mutex));
/* Solaris manual said that spurious wakeups may occur: we /* Solaris manual said that spurious wakeups may occur: we
have to check if the event really has been signaled after have to check if the event really has been signaled after
we came here to wait */ we came here to wait */
} }
os_fast_mutex_unlock(&event->os_mutex);
} }
/**********************************************************//** /**********************************************************//**
...@@ -657,7 +634,6 @@ os_event_wait_time_low( ...@@ -657,7 +634,6 @@ os_event_wait_time_low(
{ {
ibool timed_out = FALSE; ibool timed_out = FALSE;
ib_int64_t old_signal_count;
#ifdef __WIN__ #ifdef __WIN__
DWORD time_in_ms; DWORD time_in_ms;
...@@ -727,15 +703,12 @@ os_event_wait_time_low( ...@@ -727,15 +703,12 @@ os_event_wait_time_low(
os_fast_mutex_lock(&event->os_mutex); os_fast_mutex_lock(&event->os_mutex);
if (reset_sig_count) { if (!reset_sig_count) {
old_signal_count = reset_sig_count; reset_sig_count = event->signal_count;
} else {
old_signal_count = event->signal_count;
} }
do { do {
if (event->is_set == TRUE if (event->is_set || event->signal_count != reset_sig_count) {
|| event->signal_count != old_signal_count) {
break; break;
} }
...@@ -753,11 +726,6 @@ os_event_wait_time_low( ...@@ -753,11 +726,6 @@ os_event_wait_time_low(
os_fast_mutex_unlock(&event->os_mutex); os_fast_mutex_unlock(&event->os_mutex);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0); return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
} }
......
...@@ -3082,11 +3082,7 @@ suspend_thread: ...@@ -3082,11 +3082,7 @@ suspend_thread:
os_event_wait(slot->event); os_event_wait(slot->event);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
/* This is only extra safety, the thread should exit
already when the event wait ends */
os_thread_exit(NULL); os_thread_exit(NULL);
} }
/* When there is user activity, InnoDB will set the event and the /* When there is user activity, InnoDB will set the event and the
......
...@@ -2122,17 +2122,9 @@ innobase_shutdown_for_mysql(void) ...@@ -2122,17 +2122,9 @@ innobase_shutdown_for_mysql(void)
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
/* In a 'very fast' shutdown, we do not need to wait for these threads
to die; all which counts is that we flushed the log; a 'very fast'
shutdown is essentially a crash. */
if (srv_fast_shutdown == 2) {
return(DB_SUCCESS);
}
/* All threads end up waiting for certain events. Put those events /* All threads end up waiting for certain events. Put those events
to the signaled state. Then the threads will exit themselves in to the signaled state. Then the threads will exit themselves after
os_thread_event_wait(). */ os_event_wait(). */
for (i = 0; i < 1000; i++) { for (i = 0; i < 1000; i++) {
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
......
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