diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-12-13 14:16:15 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-12-13 14:17:26 +0200 |
commit | 58eb4e5db9e333768cc927d5d5a63d68fbd74548 (patch) | |
tree | 85ef8e50f1d5090e28d06fa29d72f3266492f9e1 | |
parent | 0e69d0b094365c36d01180d10fcc6534143a25b5 (diff) | |
download | mariadb-git-58eb4e5db9e333768cc927d5d5a63d68fbd74548.tar.gz |
MDEV-14422 Assertion failure in trx_purge_run() on shutdown
row_quiesce_table_start(), row_quiesce_table_complete():
Use the more appropriate predicate srv_undo_sources for skipping
purge control. (This change alone is insufficient; it is possible
that this predicate will change during the call to trx_purge_stop()
or trx_purge_run().)
trx_purge_stop(), trx_purge_run(): Tolerate PURGE_STATE_EXIT.
It is very well possible to initiate shutdown soon after the statement
FLUSH TABLES FOR EXPORT has been submitted to execution.
srv_purge_coordinator_thread(): Ensure that the wait for purge_sys->event
in trx_purge_stop() will terminate when the coordinator thread exits.
-rw-r--r-- | storage/innobase/row/row0quiesce.cc | 4 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 3 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.cc | 70 |
3 files changed, 40 insertions, 37 deletions
diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index dd6289c91e6..21cc67620f6 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -520,7 +520,7 @@ row_quiesce_table_start( ut_ad(fil_space_get(table->space) != NULL); ib::info() << "Sync to disk of " << table->name << " started."; - if (trx_purge_state() != PURGE_STATE_DISABLED) { + if (srv_undo_sources) { trx_purge_stop(); } @@ -603,7 +603,7 @@ row_quiesce_table_complete( ib::info() << "Deleting the meta-data file '" << cfg_name << "'"; } - if (trx_purge_state() != PURGE_STATE_DISABLED) { + if (srv_undo_sources) { trx_purge_run(); } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index d9eeaa82117..19be088912a 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2872,6 +2872,9 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( purge_sys->running = false; + /* Ensure that the wait in trx_purge_stop() will terminate. */ + os_event_set(purge_sys->event); + rw_lock_x_unlock(&purge_sys->latch); #ifdef UNIV_DEBUG_THREAD_CREATION diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 61c36637a4e..4fd9333c0ba 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -1770,52 +1770,48 @@ void trx_purge_stop(void) /*================*/ { - ut_a(srv_n_purge_threads > 0); - rw_lock_x_lock(&purge_sys->latch); - const int64_t sig_count = os_event_reset(purge_sys->event); - const purge_state_t state = purge_sys->state; - - ut_a(state == PURGE_STATE_RUN || state == PURGE_STATE_STOP); - - ++purge_sys->n_stop; - - if (state == PURGE_STATE_RUN) { + switch (purge_sys->state) { + case PURGE_STATE_INIT: + case PURGE_STATE_DISABLED: + ut_error; + case PURGE_STATE_EXIT: + /* Shutdown must have been initiated during + FLUSH TABLES FOR EXPORT. */ + ut_ad(!srv_undo_sources); +unlock: + rw_lock_x_unlock(&purge_sys->latch); + break; + case PURGE_STATE_STOP: + ut_ad(srv_n_purge_threads > 0); + ++purge_sys->n_stop; + purge_sys->state = PURGE_STATE_STOP; + if (!purge_sys->running) { + goto unlock; + } + ib::info() << "Waiting for purge to stop"; + do { + rw_lock_x_unlock(&purge_sys->latch); + os_thread_sleep(10000); + rw_lock_x_lock(&purge_sys->latch); + } while (purge_sys->running); + goto unlock; + case PURGE_STATE_RUN: + ut_ad(srv_n_purge_threads > 0); + ++purge_sys->n_stop; ib::info() << "Stopping purge"; /* We need to wakeup the purge thread in case it is suspended, so that it can acknowledge the state change. */ + const int64_t sig_count = os_event_reset(purge_sys->event); + purge_sys->state = PURGE_STATE_STOP; srv_purge_wakeup(); - } - - purge_sys->state = PURGE_STATE_STOP; - - if (state != PURGE_STATE_STOP) { rw_lock_x_unlock(&purge_sys->latch); /* Wait for purge coordinator to signal that it is suspended. */ os_event_wait_low(purge_sys->event, sig_count); - } else { - bool once = true; - - /* Wait for purge to signal that it has actually stopped. */ - while (purge_sys->running) { - - if (once) { - ib::info() << "Waiting for purge to stop"; - once = false; - } - - rw_lock_x_unlock(&purge_sys->latch); - - os_thread_sleep(10000); - - rw_lock_x_lock(&purge_sys->latch); - } - - rw_lock_x_unlock(&purge_sys->latch); } MONITOR_INC_VALUE(MONITOR_PURGE_STOP_COUNT, 1); @@ -1830,8 +1826,12 @@ trx_purge_run(void) rw_lock_x_lock(&purge_sys->latch); switch (purge_sys->state) { - case PURGE_STATE_INIT: case PURGE_STATE_EXIT: + /* Shutdown must have been initiated during + FLUSH TABLES FOR EXPORT. */ + ut_ad(!srv_undo_sources); + break; + case PURGE_STATE_INIT: case PURGE_STATE_DISABLED: ut_error; |