diff options
author | Paul McCullagh <paul.mccullagh@primebase.org> | 2009-09-03 08:15:03 +0200 |
---|---|---|
committer | Paul McCullagh <paul.mccullagh@primebase.org> | 2009-09-03 08:15:03 +0200 |
commit | f58512d8b719b70250edf433b8aed72db382bb94 (patch) | |
tree | 7c3f00cbd742e22be858eb71aa99de46e181d1e8 /storage/pbxt | |
parent | d841ea23ef0465e7cc0a060a1b1a6faf0f4804b8 (diff) | |
download | mariadb-git-f58512d8b719b70250edf433b8aed72db382bb94.tar.gz |
Fixed a bug that caused MySQL to crash on shutdown, if startup fails due to an incorrect command line parameter
Diffstat (limited to 'storage/pbxt')
-rw-r--r-- | storage/pbxt/ChangeLog | 4 | ||||
-rw-r--r-- | storage/pbxt/src/datalog_xt.cc | 6 | ||||
-rw-r--r-- | storage/pbxt/src/filesys_xt.cc | 5 | ||||
-rw-r--r-- | storage/pbxt/src/ha_pbxt.cc | 15 | ||||
-rw-r--r-- | storage/pbxt/src/memory_xt.cc | 2 | ||||
-rw-r--r-- | storage/pbxt/src/myxt_xt.cc | 70 | ||||
-rw-r--r-- | storage/pbxt/src/myxt_xt.h | 1 | ||||
-rw-r--r-- | storage/pbxt/src/restart_xt.cc | 91 | ||||
-rw-r--r-- | storage/pbxt/src/restart_xt.h | 3 | ||||
-rw-r--r-- | storage/pbxt/src/strutil_xt.cc | 2 | ||||
-rw-r--r-- | storage/pbxt/src/tabcache_xt.cc | 3 | ||||
-rw-r--r-- | storage/pbxt/src/thread_xt.cc | 9 | ||||
-rw-r--r-- | storage/pbxt/src/xaction_xt.cc | 6 | ||||
-rw-r--r-- | storage/pbxt/src/xactlog_xt.cc | 3 | ||||
-rw-r--r-- | storage/pbxt/src/xt_errno.h | 2 |
15 files changed, 200 insertions, 22 deletions
diff --git a/storage/pbxt/ChangeLog b/storage/pbxt/ChangeLog index 2bb7fdf5585..dabfea6c168 100644 --- a/storage/pbxt/ChangeLog +++ b/storage/pbxt/ChangeLog @@ -1,6 +1,10 @@ PBXT Release Notes ================== +------- 1.0.08d RC2 - 2009-09-02 + +RN267: Fixed a bug that caused MySQL to crash on shutdown, after an incorrect command line parameter was given. The crash occurred because the background recovery task was not cleaned up before the PBXT engine was de-initialized. + ------- 1.0.08c RC2 - 2009-08-18 RN266: Updated BLOB streaming glue, used with the PBMS engine. The glue code is now identical to the version of "1.0.08-rc-pbms" version of PBXT available from http://blobstreaming.org/download. diff --git a/storage/pbxt/src/datalog_xt.cc b/storage/pbxt/src/datalog_xt.cc index 63a13e4e038..f1a1f23df63 100644 --- a/storage/pbxt/src/datalog_xt.cc +++ b/storage/pbxt/src/datalog_xt.cc @@ -2015,7 +2015,8 @@ static void *dl_run_co_thread(XTThreadPtr self) int count; void *mysql_thread; - mysql_thread = myxt_create_thread(); + if (!(mysql_thread = myxt_create_thread())) + xt_throw(self); while (!self->t_quit) { try_(a) { @@ -2068,7 +2069,10 @@ static void *dl_run_co_thread(XTThreadPtr self) } } + /* + * {MYSQL-THREAD-KILL} myxt_destroy_thread(mysql_thread, TRUE); + */ return NULL; } diff --git a/storage/pbxt/src/filesys_xt.cc b/storage/pbxt/src/filesys_xt.cc index 19b91864007..2147626b20d 100644 --- a/storage/pbxt/src/filesys_xt.cc +++ b/storage/pbxt/src/filesys_xt.cc @@ -55,6 +55,7 @@ //#define DEBUG_TRACE_MAP_IO //#define DEBUG_TRACE_FILES //#define INJECT_WRITE_REMAP_ERROR +/* This is required to make testing on the Mac faster: */ #endif #ifdef DEBUG_TRACE_FILES @@ -62,6 +63,10 @@ #define PRINTF xt_trace #endif +#if defined(XT_MAC) && defined(F_FULLFSYNC) +#undef F_FULLFSYNC +#endif + #ifdef INJECT_WRITE_REMAP_ERROR #define INJECT_REMAP_FILE_SIZE 1000000 #define INJECT_REMAP_FILE_TYPE "xtd" diff --git a/storage/pbxt/src/ha_pbxt.cc b/storage/pbxt/src/ha_pbxt.cc index 3d9b2d15156..315b7ff74d6 100644 --- a/storage/pbxt/src/ha_pbxt.cc +++ b/storage/pbxt/src/ha_pbxt.cc @@ -71,6 +71,7 @@ extern "C" char **session_query(Session *session); #include "tabcache_xt.h" #include "systab_xt.h" #include "xaction_xt.h" +#include "restart_xt.h" #ifdef DEBUG //#define XT_USE_SYS_PAR_DEBUG_SIZES @@ -105,8 +106,6 @@ static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share); static void ha_close_open_tables(XTThreadPtr self, XTSharePtr share, ha_pbxt *mine); -extern void xt_xres_start_database_recovery(XTThreadPtr self); - #ifdef TRACE_STATEMENTS #ifdef PRINT_STATEMENTS @@ -463,8 +462,14 @@ xtPublic void xt_ha_open_database_of_table(XTThreadPtr self, XTPathStrPtr XT_UNU if (!self->st_database) { if (!pbxt_database) { xt_open_database(self, mysql_real_data_home, TRUE); - pbxt_database = self->st_database; - xt_heap_reference(self, pbxt_database); + /* {GLOBAL-DB} + * This can be done at the same time as the recovery thread, + * strictly speaking I need a lock. + */ + if (!pbxt_database) { + pbxt_database = self->st_database; + xt_heap_reference(self, pbxt_database); + } } else xt_use_database(self, pbxt_database, XT_FOR_USER); @@ -963,6 +968,8 @@ static void pbxt_call_exit(XTThreadPtr self) */ static void ha_exit(XTThreadPtr self) { + xt_xres_wait_for_recovery(self); + /* Wrap things up... */ xt_unuse_database(self, self); /* Just in case the main thread has a database in use (for testing)? */ /* This may cause the streaming engine to cleanup connections and diff --git a/storage/pbxt/src/memory_xt.cc b/storage/pbxt/src/memory_xt.cc index 6fb39396098..a920a47e29b 100644 --- a/storage/pbxt/src/memory_xt.cc +++ b/storage/pbxt/src/memory_xt.cc @@ -34,7 +34,7 @@ #include "trace_xt.h" #ifdef DEBUG -#define RECORD_MM +//#define RECORD_MM #endif #ifdef DEBUG diff --git a/storage/pbxt/src/myxt_xt.cc b/storage/pbxt/src/myxt_xt.cc index 5bac39200c2..fdcc078c957 100644 --- a/storage/pbxt/src/myxt_xt.cc +++ b/storage/pbxt/src/myxt_xt.cc @@ -1957,7 +1957,7 @@ static TABLE *my_open_table(XTThreadPtr self, XTDatabaseHPtr XT_UNUSED(db), XTPa xt_free(self, table); lex_end(&new_lex); thd->lex = old_lex; - xt_throw_ulxterr(XT_CONTEXT, XT_ERR_LOADING_MYSQL_DIC, (u_long) error); + xt_throw_sulxterr(XT_CONTEXT, XT_ERR_LOADING_MYSQL_DIC, tab_path->ps_path, (u_long) error); return NULL; } #else @@ -1975,11 +1975,23 @@ static TABLE *my_open_table(XTThreadPtr self, XTDatabaseHPtr XT_UNUSED(db), XTPa #endif #endif + /* If MySQL shutsdown while we are just starting up, they + * they kill the plugin sub-system before calling + * shutdown for the engine! + */ + if (!ha_resolve_by_legacy_type(thd, DB_TYPE_PBXT)) { + xt_free(self, table); + lex_end(&new_lex); + thd->lex = old_lex; + xt_throw_xterr(XT_CONTEXT, XT_ERR_MYSQL_SHUTDOWN); + return NULL; + } + if ((error = open_table_def(thd, share, 0))) { xt_free(self, table); lex_end(&new_lex); thd->lex = old_lex; - xt_throw_ulxterr(XT_CONTEXT, XT_ERR_LOADING_MYSQL_DIC, (u_long) error); + xt_throw_sulxterr(XT_CONTEXT, XT_ERR_LOADING_MYSQL_DIC, tab_path->ps_path, (u_long) error); return NULL; } @@ -1992,7 +2004,7 @@ static TABLE *my_open_table(XTThreadPtr self, XTDatabaseHPtr XT_UNUSED(db), XTPa xt_free(self, table); lex_end(&new_lex); thd->lex = old_lex; - xt_throw_ulxterr(XT_CONTEXT, XT_ERR_LOADING_MYSQL_DIC, (u_long) error); + xt_throw_sulxterr(XT_CONTEXT, XT_ERR_LOADING_MYSQL_DIC, tab_path->ps_path, (u_long) error); return NULL; } #endif @@ -2959,6 +2971,46 @@ xtPublic void *myxt_create_thread() return NULL; } + /* + * Unfortunately, if PBXT is the default engine, and we are shutting down + * then global_system_variables.table_plugin may be NULL. Which will cause + * a crash if we try to create a thread! + * + * The following call in plugin_shutdown() sets the global reference + * to NULL: + * + * unlock_variables(NULL, &global_system_variables); + * + * Later plugin_deinitialize() is called. + * + * The following stack is an example crash which occurs when I call + * myxt_create_thread() in ha_exit(), to force the error. + * + * if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED)) + * pi is NULL! + * #0 0x002ff684 in intern_plugin_lock at sql_plugin.cc:617 + * #1 0x0030296d in plugin_thdvar_init at sql_plugin.cc:2432 + * #2 0x000db4a4 in THD::init at sql_class.cc:756 + * #3 0x000e02ed in THD::THD at sql_class.cc:638 + * #4 0x00e2678d in myxt_create_thread at myxt_xt.cc:2990 + * #5 0x00e05d43 in ha_exit at ha_pbxt.cc:1011 + * #6 0x00e065c2 in pbxt_end at ha_pbxt.cc:1330 + * #7 0x00e065df in pbxt_panic at ha_pbxt.cc:1343 + * #8 0x0023e57d in ha_finalize_handlerton at handler.cc:392 + * #9 0x002ffc8b in plugin_deinitialize at sql_plugin.cc:816 + * #10 0x003037d9 in plugin_shutdown at sql_plugin.cc:1572 + * #11 0x000f7b2b in clean_up at mysqld.cc:1266 + * #12 0x000f7fca in unireg_end at mysqld.cc:1192 + * #13 0x000fa021 in kill_server at mysqld.cc:1134 + * #14 0x000fa6df in kill_server_thread at mysqld.cc:1155 + * #15 0x91fdb155 in _pthread_start + * #16 0x91fdb012 in thread_start + */ + if (!global_system_variables.table_plugin) { + xt_register_xterr(XT_REG_CONTEXT, XT_ERR_MYSQL_NO_THREAD); + return NULL; + } + if (!(new_thd = new THD())) { my_thread_end(); xt_register_error(XT_REG_CONTEXT, XT_ERR_MYSQL_ERROR, 0, "Unable to create MySQL thread (THD)"); @@ -2977,6 +3029,10 @@ xtPublic void *myxt_create_thread() xtPublic void myxt_destroy_thread(void *, xtBool) { } + +xtPublic void myxt_delete_remaining_thread() +{ +} #else xtPublic void myxt_destroy_thread(void *thread, xtBool end_threads) { @@ -3004,6 +3060,14 @@ xtPublic void myxt_destroy_thread(void *thread, xtBool end_threads) if (end_threads) my_thread_end(); } + +xtPublic void myxt_delete_remaining_thread() +{ + THD *thd; + + if ((thd = current_thd)) + myxt_destroy_thread((void *) thd, TRUE); +} #endif xtPublic XTThreadPtr myxt_get_self() diff --git a/storage/pbxt/src/myxt_xt.h b/storage/pbxt/src/myxt_xt.h index 3843802eeaa..484440a15b6 100644 --- a/storage/pbxt/src/myxt_xt.h +++ b/storage/pbxt/src/myxt_xt.h @@ -81,6 +81,7 @@ struct charset_info_st *myxt_getcharset(bool convert); void *myxt_create_thread(); void myxt_destroy_thread(void *thread, xtBool end_threads); +void myxt_delete_remaining_thread(); XTThreadPtr myxt_get_self(); int myxt_statistics_fill_table(XTThreadPtr self, void *th, void *ta, void *co, MX_CONST void *ch); diff --git a/storage/pbxt/src/restart_xt.cc b/storage/pbxt/src/restart_xt.cc index e2668184857..0e0e4306a2e 100644 --- a/storage/pbxt/src/restart_xt.cc +++ b/storage/pbxt/src/restart_xt.cc @@ -2551,7 +2551,8 @@ static void *xres_cp_run_thread(XTThreadPtr self) int count; void *mysql_thread; - mysql_thread = myxt_create_thread(); + if (!(mysql_thread = myxt_create_thread())) + xt_throw(self); while (!self->t_quit) { try_(a) { @@ -2588,7 +2589,10 @@ static void *xres_cp_run_thread(XTThreadPtr self) } } + /* + * {MYSQL-THREAD-KILL} myxt_destroy_thread(mysql_thread, TRUE); + */ return NULL; } @@ -3179,22 +3183,74 @@ xtPublic void xt_dump_xlogs(XTDatabaseHPtr db, xtLogID start_log) * D A T A B A S E R E C O V E R Y T H R E A D */ -extern XTDatabaseHPtr pbxt_database; +extern XTDatabaseHPtr pbxt_database; +static XTThreadPtr xres_recovery_thread; static void *xn_xres_run_recovery_thread(XTThreadPtr self) { THD *mysql_thread; - mysql_thread = (THD *)myxt_create_thread(); + if (!(mysql_thread = (THD *) myxt_create_thread())) + xt_throw(self); - while(!ha_resolve_by_legacy_type(mysql_thread, DB_TYPE_PBXT)) + while (!xres_recovery_thread->t_quit && !ha_resolve_by_legacy_type(mysql_thread, DB_TYPE_PBXT)) xt_sleep_milli_second(1); - xt_open_database(self, mysql_real_data_home, TRUE); - pbxt_database = self->st_database; - xt_heap_reference(self, pbxt_database); + if (!xres_recovery_thread->t_quit) { + /* {GLOBAL-DB} + * It can happen that something will just get in before this + * thread and open/recover the database! + */ + if (!pbxt_database) { + try_(a) { + xt_open_database(self, mysql_real_data_home, TRUE); + /* This can be done at the same time by a foreground thread, + * strictly speaking I need a lock. + */ + if (!pbxt_database) { + pbxt_database = self->st_database; + xt_heap_reference(self, pbxt_database); + } + } + catch_(a) { + xt_log_and_clear_exception(self); + } + cont_(a); + } + } + + /* + * {MYSQL-THREAD-KILL} + * Here is the problem with destroying the thread at this + * point. If we had an error started, then it can lead + * to a callback into pbxt: pbxt_panic(). + * + * This will shutdown things, making it impossible quite the + * thread and do a cleanup. Solution: + * + * Move the MySQL thread descruction to a later point! + * + * sql/mysqld --no-defaults --basedir=~/maria/trunk + * --character-sets-dir=~/maria/trunk/sql/share/charsets + * --language=~/maria/trunk/sql/share/english + * --skip-networking --datadir=/tmp/x --skip-grant-tables --nonexistentoption + * + * #0 0x003893f9 in xt_exit_databases at database_xt.cc:304 + * #1 0x0039dc7e in pbxt_end at ha_pbxt.cc:947 + * #2 0x0039dd27 in pbxt_panic at ha_pbxt.cc:1289 + * #3 0x001d619e in ha_finalize_handlerton at handler.cc:391 + * #4 0x00279d22 in plugin_deinitialize at sql_plugin.cc:816 + * #5 0x0027bcf5 in reap_plugins at sql_plugin.cc:904 + * #6 0x0027c38c in plugin_thdvar_cleanup at sql_plugin.cc:2513 + * #7 0x000c0db2 in THD::~THD at sql_class.cc:934 + * #8 0x003b025b in myxt_destroy_thread at myxt_xt.cc:2999 + * #9 0x003b66b5 in xn_xres_run_recovery_thread at restart_xt.cc:3196 + * #10 0x003cbfbb in thr_main at thread_xt.cc:1020 + * myxt_destroy_thread(mysql_thread, TRUE); + */ + xres_recovery_thread = NULL; return NULL; } @@ -3204,6 +3260,23 @@ xtPublic void xt_xres_start_database_recovery(XTThreadPtr self) sprintf(name, "DB-RECOVERY-%s", xt_last_directory_of_path(mysql_real_data_home)); xt_remove_dir_char(name); - XTThreadPtr thread = xt_create_daemon(self, name); - xt_run_thread(self, thread, xn_xres_run_recovery_thread); + + xres_recovery_thread = xt_create_daemon(self, name); + xt_run_thread(self, xres_recovery_thread, xn_xres_run_recovery_thread); +} + +xtPublic void xt_xres_wait_for_recovery(XTThreadPtr self) +{ + XTThreadPtr thr_rec; + + /* {MYSQL-THREAD-KILL} + * Stack above shows that his is possible! + */ + if ((thr_rec = xres_recovery_thread) && (self != xres_recovery_thread)) { + xtThreadID tid = thr_rec->t_id; + + xt_terminate_thread(self, thr_rec); + + xt_wait_for_thread(tid, TRUE); + } } diff --git a/storage/pbxt/src/restart_xt.h b/storage/pbxt/src/restart_xt.h index af185223ccb..bcef7191443 100644 --- a/storage/pbxt/src/restart_xt.h +++ b/storage/pbxt/src/restart_xt.h @@ -131,6 +131,7 @@ xtWord8 xt_bytes_since_last_checkpoint(struct XTDatabase *db, xtLogID curr_log_i void xt_print_log_record(xtLogID log, off_t offset, XTXactLogBufferDPtr record); void xt_dump_xlogs(struct XTDatabase *db, xtLogID start_log); -xtPublic void xt_xres_start_database_recovery(XTThreadPtr self, const char *path); +void xt_xres_start_database_recovery(XTThreadPtr self); +void xt_xres_wait_for_recovery(XTThreadPtr self); #endif diff --git a/storage/pbxt/src/strutil_xt.cc b/storage/pbxt/src/strutil_xt.cc index a640d880815..dee92c67df4 100644 --- a/storage/pbxt/src/strutil_xt.cc +++ b/storage/pbxt/src/strutil_xt.cc @@ -368,7 +368,7 @@ xtPublic void xt_int8_to_byte_size(xtInt8 value, char *string) /* Version number must also be set in configure.in! */ xtPublic c_char *xt_get_version(void) { - return "1.0.08c RC"; + return "1.0.08d RC"; } /* Copy and URL decode! */ diff --git a/storage/pbxt/src/tabcache_xt.cc b/storage/pbxt/src/tabcache_xt.cc index cba89a39cc2..7e8cc9e1f6e 100644 --- a/storage/pbxt/src/tabcache_xt.cc +++ b/storage/pbxt/src/tabcache_xt.cc @@ -1178,7 +1178,10 @@ static void *tabc_fr_run_thread(XTThreadPtr self) } } + /* + * {MYSQL-THREAD-KILL} myxt_destroy_thread(mysql_thread, TRUE); + */ return NULL; } diff --git a/storage/pbxt/src/thread_xt.cc b/storage/pbxt/src/thread_xt.cc index a15b600a431..9509df6184d 100644 --- a/storage/pbxt/src/thread_xt.cc +++ b/storage/pbxt/src/thread_xt.cc @@ -625,7 +625,7 @@ static c_char *thr_get_err_string(int xt_err) case XT_ERR_NO_REFERENCED_ROW: str = "Constraint: `%s`"; break; // "Foreign key '%s', referenced row does not exist" case XT_ERR_ROW_IS_REFERENCED: str = "Constraint: `%s`"; break; // "Foreign key '%s', has a referencing row" case XT_ERR_BAD_DICTIONARY: str = "Internal dictionary does not match MySQL dictionary"; break; - case XT_ERR_LOADING_MYSQL_DIC: str = "Error %s loading MySQL .frm file"; break; + case XT_ERR_LOADING_MYSQL_DIC: str = "Error loading %s.frm file, MySQL error: %s"; break; case XT_ERR_COLUMN_IS_NOT_NULL: str = "Column `%s` is NOT NULL"; break; case XT_ERR_INCORRECT_NO_OF_COLS: str = "Incorrect number of columns near %s"; break; case XT_ERR_FK_ON_TEMP_TABLE: str = "Cannot create foreign key on temporary table"; break; @@ -656,6 +656,8 @@ static c_char *thr_get_err_string(int xt_err) case XT_ERR_NEW_TYPE_OF_XLOG: str = "Transaction log %s, is using a newer format, upgrade required"; break; case XT_ERR_NO_BEFORE_IMAGE: str = "Internal error: no before image"; break; case XT_ERR_FK_REF_TEMP_TABLE: str = "Foreign key may not reference temporary table"; break; + case XT_ERR_MYSQL_SHUTDOWN: str = "Cannot open table, MySQL has shutdown"; break; + case XT_ERR_MYSQL_NO_THREAD: str = "Cannot create thread, MySQL has shutdown"; break; default: str = "Unknown XT error"; break; } return str; @@ -1026,6 +1028,11 @@ extern "C" void *thr_main(void *data) outer_(); xt_free_thread(self); + + /* {MYSQL-THREAD-KILL} + * Clean up any remaining MySQL thread! + */ + myxt_delete_remaining_thread(); return return_data; } diff --git a/storage/pbxt/src/xaction_xt.cc b/storage/pbxt/src/xaction_xt.cc index a27c9e65634..82039ace2b3 100644 --- a/storage/pbxt/src/xaction_xt.cc +++ b/storage/pbxt/src/xaction_xt.cc @@ -2529,7 +2529,8 @@ static void *xn_sw_run_thread(XTThreadPtr self) int count; void *mysql_thread; - mysql_thread = myxt_create_thread(); + if (!(mysql_thread = myxt_create_thread())) + xt_throw(self); while (!self->t_quit) { try_(a) { @@ -2586,7 +2587,10 @@ static void *xn_sw_run_thread(XTThreadPtr self) db->db_sw_idle = XT_THREAD_BUSY; } + /* + * {MYSQL-THREAD-KILL} myxt_destroy_thread(mysql_thread, TRUE); + */ return NULL; } diff --git a/storage/pbxt/src/xactlog_xt.cc b/storage/pbxt/src/xactlog_xt.cc index 9e3e64ef78d..fac32ea0a09 100644 --- a/storage/pbxt/src/xactlog_xt.cc +++ b/storage/pbxt/src/xactlog_xt.cc @@ -2610,7 +2610,10 @@ static void *xlog_wr_run_thread(XTThreadPtr self) db->db_wr_idle = XT_THREAD_BUSY; } + /* + * {MYSQL-THREAD-KILL} myxt_destroy_thread(mysql_thread, TRUE); + */ return NULL; } diff --git a/storage/pbxt/src/xt_errno.h b/storage/pbxt/src/xt_errno.h index 4d74589efe3..60e43d5fdfa 100644 --- a/storage/pbxt/src/xt_errno.h +++ b/storage/pbxt/src/xt_errno.h @@ -117,6 +117,8 @@ #define XT_ERR_NEW_TYPE_OF_XLOG -93 #define XT_ERR_NO_BEFORE_IMAGE -94 #define XT_ERR_FK_REF_TEMP_TABLE -95 +#define XT_ERR_MYSQL_SHUTDOWN -98 +#define XT_ERR_MYSQL_NO_THREAD -99 #ifdef XT_WIN #define XT_ENOMEM ERROR_NOT_ENOUGH_MEMORY |