diff options
author | unknown <monty@mysql.com> | 2004-05-17 01:52:13 +0300 |
---|---|---|
committer | unknown <monty@mysql.com> | 2004-05-17 01:52:13 +0300 |
commit | a495f76c8eed91414d321cc7536d46d1bf7bcfee (patch) | |
tree | b9fa88577b516df5fb27de3970ec9eab9aaef532 | |
parent | 8ef62cc1ef3e2b16795fa5fbbc45bcdf422f344c (diff) | |
parent | fa163d0ba5f5fc22dbadbd66255879ceeb895c27 (diff) | |
download | mariadb-git-a495f76c8eed91414d321cc7536d46d1bf7bcfee.tar.gz |
Merge with 4.0.20
BitKeeper/etc/logging_ok:
auto-union
client/mysql.cc:
Auto merged
client/mysqltest.c:
Auto merged
innobase/btr/btr0btr.c:
Auto merged
innobase/dict/dict0dict.c:
Auto merged
innobase/dict/dict0load.c:
Auto merged
innobase/eval/eval0eval.c:
Auto merged
innobase/ibuf/ibuf0ibuf.c:
Auto merged
innobase/include/ut0mem.h:
Auto merged
innobase/lock/lock0lock.c:
Auto merged
innobase/row/row0ins.c:
Auto merged
innobase/row/row0mysql.c:
Auto merged
innobase/row/row0sel.c:
Auto merged
innobase/row/row0umod.c:
Auto merged
innobase/row/row0upd.c:
Auto merged
innobase/trx/trx0trx.c:
Auto merged
innobase/ut/ut0dbg.c:
Auto merged
innobase/ut/ut0mem.c:
Auto merged
myisam/mi_dynrec.c:
Auto merged
mysql-test/r/innodb.result:
Auto merged
mysql-test/t/fulltext.test:
Auto merged
mysql-test/t/rpl_rotate_logs.test:
Auto merged
scripts/make_binary_distribution.sh:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/slave.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_show.cc:
Auto merged
innobase/os/os0file.c:
Merge with 4.0.20
Ensure that we call F_UNLCK for files on which we call F_WRLCK.
This is to ensure that this code will be portable accross most platforms.
myisam/ft_boolean_search.c:
Merge with 4.0.20 (keep original file)
myisam/ft_parser.c:
Merge with 4.0.20 (keep original file)
myisam/ftdefs.h:
Merge with 4.0.20 (keep original file)
40 files changed, 287 insertions, 99 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index ddc6441f08a..cf80a5594e4 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2404,6 +2404,10 @@ static int com_shell(String *buffer, char *line __attribute__((unused))) { char *shell_cmd; + + /* Skip space from line begin */ + while (isspace(*line)) + line++; if (!(shell_cmd = strchr(line, ' '))) { put_info("Usage: \\! shell-command", INFO_ERROR); diff --git a/client/mysqldump.c b/client/mysqldump.c index 20792f8c025..97ae0070e04 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1264,18 +1264,32 @@ static char *field_escape(char *to,const char *from,uint length) } /* field_escape */ +static char *alloc_query_str(ulong size) +{ + char *query; + + if (!(query= (char*) my_malloc(size, MYF(MY_WME)))) + { + ignore_errors= 0; /* Fatal error */ + safe_exit(EX_MYSQLERR); /* Force exit */ + } + return query; +} + /* ** dumpTable saves database contents as a series of INSERT statements. */ static void dumpTable(uint numFields, char *table) { - char query[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3]; + char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3]; char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table; + char *query= query_buf; MYSQL_RES *res; MYSQL_FIELD *field; MYSQL_ROW row; ulong rownr, row_break, total_length, init_length; const char *table_type; + int error= 0; result_table= quote_name(table,table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); @@ -1321,8 +1335,11 @@ static void dumpTable(uint numFields, char *table) sprintf(buff," FROM %s", result_table); end= strmov(end,buff); if (where) - end= strxmov(end, " WHERE ",where,NullS); - if (mysql_query(sock, query)) + { + query= alloc_query_str((ulong) (strlen(where) + (end - query) + 10)); + end= strxmov(query, query_buf, " WHERE ", where, NullS); + } + if (mysql_real_query(sock, query, (uint) (end - query))) { DBerror(sock, "when executing 'SELECT INTO OUTFILE'"); return; @@ -1339,14 +1356,16 @@ static void dumpTable(uint numFields, char *table) { if (!opt_xml && opt_comments) fprintf(md_result_file,"-- WHERE: %s\n",where); - strxmov(strend(query), " WHERE ",where,NullS); + query= alloc_query_str((ulong) (strlen(where) + strlen(query) + 10)); + strxmov(query, query_buf, " WHERE ", where, NullS); } if (!opt_xml && !opt_compact) fputs("\n", md_result_file); if (mysql_query(sock, query)) { DBerror(sock, "when retrieving data from server"); - return; + error= EX_CONSCHECK; + goto err; } if (quick) res=mysql_use_result(sock); @@ -1355,7 +1374,8 @@ static void dumpTable(uint numFields, char *table) if (!res) { DBerror(sock, "when retrieving data from server"); - return; + error= EX_CONSCHECK; + goto err; } if (verbose) fprintf(stderr, "-- Retrieving rows...\n"); @@ -1363,8 +1383,8 @@ static void dumpTable(uint numFields, char *table) { fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n", my_progname, result_table); - safe_exit(EX_CONSCHECK); - return; + error= EX_CONSCHECK; + goto err; } if (opt_disable_keys) @@ -1402,8 +1422,8 @@ static void dumpTable(uint numFields, char *table) sprintf(query,"%s: Not enough fields from table %s! Aborting.\n", my_progname, result_table); fputs(query,stderr); - safe_exit(EX_CONSCHECK); - return; + error= EX_CONSCHECK; + goto err; } if (extended_insert) { @@ -1422,7 +1442,8 @@ static void dumpTable(uint numFields, char *table) if (dynstr_realloc(&extended_row,length * 2+2)) { fputs("Aborting dump (out of memory)",stderr); - safe_exit(EX_EOM); + error= EX_EOM; + goto err; } dynstr_append(&extended_row,"'"); extended_row.length += @@ -1458,7 +1479,8 @@ static void dumpTable(uint numFields, char *table) else if (dynstr_append(&extended_row,"NULL")) { fputs("Aborting dump (out of memory)",stderr); - safe_exit(EX_EOM); + error= EX_EOM; + goto err; } } else @@ -1552,8 +1574,8 @@ static void dumpTable(uint numFields, char *table) result_table, rownr); fputs(query,stderr); - safe_exit(EX_CONSCHECK); - return; + error= EX_CONSCHECK; + goto err; } if (opt_lock) fputs("UNLOCK TABLES;\n", md_result_file); @@ -1563,7 +1585,16 @@ static void dumpTable(uint numFields, char *table) if (opt_autocommit) fprintf(md_result_file, "commit;\n"); mysql_free_result(res); - } + if (query != query_buf) + my_free(query, MYF(MY_ALLOW_ZERO_PTR)); + } + return; + +err: + if (query != query_buf) + my_free(query, MYF(MY_ALLOW_ZERO_PTR)); + safe_exit(error); + return; } /* dumpTable */ diff --git a/client/mysqltest.c b/client/mysqltest.c index be5dac1c9d9..2cd395a02b8 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1097,7 +1097,7 @@ int do_sync_with_master2(const char* p) MYSQL_ROW row; MYSQL* mysql = &cur_con->mysql; char query_buf[FN_REFLEN+128]; - int offset = 0; + int offset= 0, tries= 0; int rpl_parse; if (!master_pos.file[0]) @@ -1112,6 +1112,9 @@ int do_sync_with_master2(const char* p) sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file, master_pos.pos + offset); + +wait_for_position: + if (mysql_query(mysql, query_buf)) die("line %u: failed in %s: %d: %s", start_lineno, query_buf, mysql_errno(mysql), mysql_error(mysql)); @@ -1122,8 +1125,20 @@ int do_sync_with_master2(const char* p) if (!(row = mysql_fetch_row(res))) die("line %u: empty result in %s", start_lineno, query_buf); if (!row[0]) - die("line %u: could not sync with master ('%s' returned NULL)", - start_lineno, query_buf); + { + /* + It may be that the slave SQL thread has not started yet, though START + SLAVE has been issued ? + */ + if (tries++ == 3) + { + die("line %u: could not sync with master ('%s' returned NULL)", + start_lineno, query_buf); + } + sleep(1); /* So at most we will wait 3 seconds and make 4 tries */ + mysql_free_result(res); + goto wait_for_position; + } mysql_free_result(res); last_result=0; if (rpl_parse) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 8388009dc9c..09f5c66f687 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -883,7 +883,7 @@ btr_page_reorganize_low( fprintf(stderr, "InnoDB: Error: page old data size %lu new data size %lu\n" "InnoDB: Error: page old max ins size %lu new max ins size %lu\n" -"InnoDB: Make a detailed bug report and send it to mysql@lists.mysql.com\n", +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", (unsigned long) data_size1, (unsigned long) data_size2, (unsigned long) max_ins_size1, (unsigned long) max_ins_size2); diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index b22d93d6bd8..c9e3ac5ec66 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -4287,5 +4287,5 @@ dict_index_name_print( fputs("index ", file); ut_print_name(file, index->name); fputs(" of table ", file); - ut_print_name(stderr, index->table_name); + ut_print_name(file, index->table_name); } diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index abb06b15ea7..bf8b4582f63 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -849,7 +849,7 @@ dict_load_table( "InnoDB: the foreign key table or the referenced table!\n" "InnoDB: The data dictionary of InnoDB is corrupt. You may need to drop\n" "InnoDB: and recreate the foreign key table or the referenced table.\n" -"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" "InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf); mutex_exit(&dict_foreign_err_mutex); diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index 7dc0bd98001..9246bb03138 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2770,7 +2770,7 @@ ibuf_insert_to_index_page( fprintf(stderr, "Bitmap bits %lu\n", (ulong) old_bits); fputs( -"InnoDB: Send a detailed bug report to mysql@lists.mysql.com!\n", stderr); +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } } } @@ -2833,7 +2833,7 @@ ibuf_delete_rec( if (!success) { fprintf(stderr, - "InnoDB: ERROR: Send the output to mysql@lists.mysql.com\n" + "InnoDB: ERROR: Submit the output to http://bugs.mysql.com\n" "InnoDB: ibuf cursor restoration fails!\n" "InnoDB: ibuf record inserted to page %lu\n", (ulong) page_no); fflush(stderr); @@ -3025,8 +3025,7 @@ ibuf_merge_or_delete_for_page( "InnoDB: We try to resolve the problem by skipping the insert buffer\n" "InnoDB: merge for this page. Please run CHECK TABLE on your tables\n" "InnoDB: to determine if they are corrupt after this.\n\n" -"InnoDB: Please make a detailed bug report and send it to\n" -"InnoDB: mysql@lists.mysql.com\n\n", +"InnoDB: Please submit a detailed bug report to http://bugs.mysql.com\n\n", (ulong) page_no, (ulong) fil_page_get_type(page)); } diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 71269cb1e4e..07d5e5a8215 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -275,13 +275,15 @@ trx_commit_step( que_thr_t* thr); /* in: query thread */ /************************************************************************** Prints info about a transaction to the standard output. The caller must -own the kernel mutex. */ +own the kernel mutex and must have called +innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or +InnoDB cannot meanwhile change the info printed here. */ void trx_print( /*======*/ FILE* f, /* in: output stream */ - trx_t* trx); /* in: transaction */ + trx_t* trx); /* in: transaction */ /* Signal to a transaction */ diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 056d502e858..223d9af78d1 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -17,6 +17,32 @@ Created 5/7/1996 Heikki Tuuri #include "dict0mem.h" #include "trx0sys.h" + +/* 2 function prototypes copied from ha_innodb.cc: */ + +/***************************************************************** +If you want to print a thd that is not associated with the current thread, +you must call this function before reserving the InnoDB kernel_mutex, to +protect MySQL from setting thd->query NULL. If you print a thd of the current +thread, we know that MySQL cannot modify thd->query, and it is not necessary +to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release +the kernel_mutex. +NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this +function! */ + +void +innobase_mysql_prepare_print_arbitrary_thd(void); +/*============================================*/ + +/***************************************************************** +Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd(). +NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this +function! */ + +void +innobase_mysql_end_print_arbitrary_thd(void); +/*========================================*/ + /* Restricts the length of search we will do in the waits-for graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 @@ -1629,7 +1655,8 @@ lock_rec_enqueue_waiting( " InnoDB: Error: a record lock wait happens in a dictionary operation!\n" "InnoDB: Table name ", stderr); ut_print_name(stderr, index->table_name); - fputs(". Send a bug report to mysql@lists.mysql.com\n", + fputs(".\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } @@ -3269,7 +3296,8 @@ lock_table_enqueue_waiting( " InnoDB: Error: a table lock wait happens in a dictionary operation!\n" "InnoDB: Table name ", stderr); ut_print_name(stderr, table->name); - fputs(". Send a bug report to mysql@lists.mysql.com\n", + fputs(".\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } @@ -3975,6 +4003,11 @@ lock_print_info( ulint i; mtr_t mtr; + /* We must protect the MySQL thd->query field with a MySQL mutex, and + because the MySQL mutex must be reserved before the kernel_mutex of + InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */ + + innobase_mysql_prepare_print_arbitrary_thd(); lock_mutex_enter_kernel(); if (lock_deadlock_found) { @@ -4038,6 +4071,7 @@ loop: if (trx == NULL) { lock_mutex_exit_kernel(); + innobase_mysql_end_print_arbitrary_thd(); ut_ad(lock_validate()); @@ -4102,6 +4136,7 @@ loop: if (load_page_first) { lock_mutex_exit_kernel(); + innobase_mysql_end_print_arbitrary_thd(); mtr_start(&mtr); @@ -4111,6 +4146,7 @@ loop: load_page_first = FALSE; + innobase_mysql_prepare_print_arbitrary_thd(); lock_mutex_enter_kernel(); goto loop; diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 79185c30f79..1a158372563 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -387,15 +387,17 @@ os_file_lock( /*=========*/ /* out: 0 on success */ int fd, /* in: file descriptor */ - const char* name) /* in: file name */ + const char* name, /* in: file name */ + uint lock_type) /* in: lock_type */ { struct flock lk; - lk.l_type = F_WRLCK; + lk.l_type = lock_type; lk.l_whence = SEEK_SET; lk.l_start = lk.l_len = 0; if (fcntl(fd, F_SETLK, &lk) == -1) { fprintf(stderr, - "InnoDB: Unable to lock %s", name); + "InnoDB: Unable to lock %s with lock %d, error: %d", + name, lock_type, errno); perror (": fcntl"); close(fd); return(-1); @@ -862,7 +864,7 @@ try_again: goto try_again; } #ifdef USE_FILE_LOCK - } else if (os_file_lock(file, name)) { + } else if (os_file_lock(file, name, F_WRLCK)) { *success = FALSE; file = -1; #endif @@ -971,7 +973,7 @@ os_file_create_simple_no_error_handling( if (file == -1) { *success = FALSE; #ifdef USE_FILE_LOCK - } else if (os_file_lock(file, name)) { + } else if (os_file_lock(file, name, F_WRLCK)) { *success = FALSE; file = -1; #endif @@ -1182,7 +1184,7 @@ try_again: goto try_again; } #ifdef USE_FILE_LOCK - } else if (os_file_lock(file, name)) { + } else if (os_file_lock(file, name, F_WRLCK)) { *success = FALSE; file = -1; #endif @@ -1383,6 +1385,9 @@ os_file_close( #else int ret; +#ifdef USE_FILE_LOCK + (void) os_file_lock(file, "unknown", F_UNLCK); +#endif ret = close(file); if (ret == -1) { @@ -1419,6 +1424,9 @@ os_file_close_no_error_handling( #else int ret; +#ifdef USE_FILE_LOCK + (void) os_file_lock(file, "unknown", F_UNLCK); +#endif ret = close(file); if (ret == -1) { diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index a3f883b49c6..062f21369a7 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -803,8 +803,7 @@ row_ins_foreign_check_on_constraint( "InnoDB: clustered record ", stderr); rec_print(stderr, clust_rec); fputs("\n" - "InnoDB: Make a detailed bug report and send it\n" - "InnoDB: to mysql@lists.mysql.com\n", stderr); +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); err = DB_SUCCESS; diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 5432add37f7..154da11da58 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -714,7 +714,7 @@ run_again: trx_start_if_not_started(trx); - err = lock_table(0, prebuilt->table, prebuilt->select_lock_type, thr); + err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); trx->error_state = err; @@ -2526,10 +2526,11 @@ row_drop_database_for_mysql( dict_table_t* table; char* table_name; int err = DB_SUCCESS; + ulint namelen = strlen(name); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(name != NULL); - ut_a(name[strlen(name) - 1] == '/'); + ut_a(name[namelen - 1] == '/'); trx->op_info = (char *) "dropping database"; @@ -2538,7 +2539,7 @@ loop: row_mysql_lock_data_dictionary(trx); while ((table_name = dict_get_first_table_name_in_db(name))) { - ut_a(strcmp(table_name, name) == 0); + ut_a(memcmp(table_name, name, namelen) == 0); table = dict_table_get_low(table_name); diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 4c43f75125c..47d61459d47 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2410,8 +2410,7 @@ row_sel_get_clust_rec_for_mysql( trx_print(stderr, thr_get_trx(thr)); fputs("\n" - "InnoDB: Make a detailed bug report and send it\n" - "InnoDB: to mysql@lists.mysql.com\n", stderr); +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } clust_rec = NULL; diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index 3c181ed5493..d47227166f3 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -441,8 +441,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( putc('\n', stderr); trx_print(stderr, thr_get_trx(thr)); fputs("\n" - "InnoDB: Make a detailed bug report and send it\n" - "InnoDB: to mysql@lists.mysql.com\n", stderr); +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } else { btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur); diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index 82eb112fc77..724e7bf91e7 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -1236,8 +1236,7 @@ row_upd_sec_index_entry( trx_print(stderr, thr_get_trx(thr)); fputs("\n" - "InnoDB: Make a detailed bug report and send it\n" - "InnoDB: to mysql@lists.mysql.com\n", stderr); +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); } else { /* Delete mark the old index record; it can already be delete marked if we return after a lock wait in diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c index 16f9f3d093d..382f723a05c 100644 --- a/innobase/trx/trx0rec.c +++ b/innobase/trx/trx0rec.c @@ -823,17 +823,16 @@ trx_undo_update_rec_get_update( if (field_no >= dict_index_get_n_fields(index)) { fprintf(stderr, - "InnoDB: Error: trying to access" - " update undo rec field %lu in ", (ulong) field_no); +"InnoDB: Error: trying to access update undo rec field %lu in ", (ulong) field_no); dict_index_name_print(stderr, index); fprintf(stderr, "\n" - "InnoDB: but index has only %lu fields\n" - "InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n" - "InnoDB: Run also CHECK TABLE ", +"InnoDB: but index has only %lu fields\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" +"InnoDB: Run also CHECK TABLE ", (ulong) dict_index_get_n_fields(index)); ut_print_name(stderr, index->table_name); fprintf(stderr, "\n" - "InnoDB: n_fields = %lu, i = %lu, ptr %p\n", +"InnoDB: n_fields = %lu, i = %lu, ptr %p\n", (ulong) n_fields, (ulong) i, ptr); return(NULL); } @@ -1271,8 +1270,7 @@ trx_undo_prev_version_build( " update undo rec for non-clustered ", stderr); dict_index_name_print(stderr, index); fputs("\n" - "InnoDB: Send a detailed bug report to" - " mysql@lists.mysql.com\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" "InnoDB: index record ", stderr); rec_print(stderr, index_rec); fputs("\n" @@ -1320,11 +1318,9 @@ trx_undo_prev_version_build( " update undo rec for table ", stderr); ut_print_name(stderr, index->table_name); fputs("\n" - "InnoDB: but the table id in the" - " undo record is wrong\n" - "InnoDB: Send a detailed bug report to " - "mysql@lists.mysql.com\n" - "InnoDB: Run also CHECK TABLE ", stderr); +"InnoDB: but the table id in the undo record is wrong\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" +"InnoDB: Run also CHECK TABLE ", stderr); ut_print_name(stderr, index->table_name); putc('\n', stderr); } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index fc0a67278d2..8128c8de13e 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1564,7 +1564,9 @@ trx_mark_sql_stat_end( /************************************************************************** Prints info about a transaction to the standard output. The caller must -own the kernel mutex. */ +own the kernel mutex and must have called +innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or +InnoDB cannot meanwhile change the info printed here. */ void trx_print( diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c index 3697e31050f..65703ec1c86 100644 --- a/innobase/ut/ut0dbg.c +++ b/innobase/ut/ut0dbg.c @@ -23,7 +23,7 @@ const char* ut_dbg_msg_assert_fail = "InnoDB: Assertion failure in thread %lu in file %s line %lu\n"; const char* ut_dbg_msg_trap = "InnoDB: We intentionally generate a memory trap.\n" -"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n" +"InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n" "InnoDB: If you get repeated assertion failures or crashes, even\n" "InnoDB: immediately after the mysqld startup, there may be\n" "InnoDB: corruption in the InnoDB tablespace. See section 6.1 of\n" diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 30a4762abe0..f64e774810d 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -311,7 +311,7 @@ static int update_backward_delete_link(MI_INFO *info, my_off_t delete_block, DBUG_RETURN(1); /* Wrong delete link */ } } - return 0; + DBUG_RETURN(0); } /* Delete datarecord from database */ diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index f93f7401081..3106602e718 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -142,6 +142,8 @@ a b MySQL has now support for full-text search select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE); a b +select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE); +a b select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN BOOLEAN MODE); a b select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE); diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 700fe1a4111..981ef23c779 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -467,7 +467,7 @@ ERROR 23000: Duplicate entry 'test2' for key 2 select * from t1; id ggid email passwd 1 this will work -4 test2 this will work +3 test2 this will work select * from t1 where id=1; id ggid email passwd 1 this will work diff --git a/mysql-test/r/rpl_server_id2.result b/mysql-test/r/rpl_server_id2.result index fde7251497a..82ab1ff85a7 100644 --- a/mysql-test/r/rpl_server_id2.result +++ b/mysql-test/r/rpl_server_id2.result @@ -4,9 +4,6 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' create table t1 (n int); reset master; stop slave; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 71ac229601d..3dee0c2fcf9 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -70,6 +70,21 @@ select min(a) from t1; min(a) -0.010 drop table t1; +create table t1 (c1 double, c2 varchar(20)); +insert t1 values (121,"16"); +select c1 + c1 * (c2 / 100) as col from t1; +col +140.36 +create table t2 select c1 + c1 * (c2 / 100) as col from t1; +select * from t2; +col +140.36 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `col` double default NULL +) TYPE=MyISAM +drop table t1,t2; create table t1 (a float); insert into t1 values (1); select max(a),min(a),avg(a) from t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 50a3d522e3d..ac88125965a 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -63,6 +63,7 @@ select * from t1 where MATCH a,b AGAINST ('"text search" "now support"' IN BOOL select * from t1 where MATCH a,b AGAINST ('"text search" -"now support"' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('"text search" +"now support"' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE); +select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE); diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test index 38e0d1bff6c..b0119526deb 100644 --- a/mysql-test/t/rpl000015.test +++ b/mysql-test/t/rpl000015.test @@ -12,7 +12,7 @@ show slave status; change master to master_host='127.0.0.1'; # The following needs to be cleaned up when change master is fixed ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT --replace_column 1 # 33 # show slave status; --replace_result $MASTER_MYPORT MASTER_PORT diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index 4e4e79adf67..0062a67ff1a 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -14,7 +14,7 @@ connection slave; sync_with_master; # The port number is different when doing the release build with # Do-compile, hence we have to replace the port number here accordingly ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; # check that the table has been ignored, because otherwise the test is nonsense diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test index 7ae0a4dc3c2..8fdccdd068d 100644 --- a/mysql-test/t/rpl_log.test +++ b/mysql-test/t/rpl_log.test @@ -89,11 +89,11 @@ connection slave; start slave; sync_with_master; show binary logs; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION +--replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION show binlog events in 'slave-bin.000001' from 4; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION +--replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION show binlog events in 'slave-bin.000002' from 4; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test index 2e54c98c014..a40736577c8 100644 --- a/mysql-test/t/rpl_log_pos.test +++ b/mysql-test/t/rpl_log_pos.test @@ -4,7 +4,7 @@ source include/master-slave.inc; show master status; sync_slave_with_master; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; stop slave; @@ -14,19 +14,19 @@ sleep 5; stop slave; change master to master_log_pos=73; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; start slave; sleep 5; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; stop slave; change master to master_log_pos=173; start slave; sleep 2; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; connection master; diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test index a28aed52ec8..cbcc115a942 100644 --- a/mysql-test/t/rpl_max_relay_size.test +++ b/mysql-test/t/rpl_max_relay_size.test @@ -28,7 +28,7 @@ set global max_relay_log_size=8192-1; # mapped to 4096 select @@global.max_relay_log_size; start slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; stop slave; @@ -37,7 +37,7 @@ set global max_relay_log_size=(5*4096); select @@global.max_relay_log_size; start slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; stop slave; @@ -46,7 +46,7 @@ set global max_relay_log_size=0; select @@global.max_relay_log_size; start slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; @@ -57,7 +57,7 @@ reset slave; # test of relay log rotation when the slave is stopped # (to make sure it does not crash). flush logs; ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; @@ -73,7 +73,7 @@ create table t1 (a int); save_master_pos; connection slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; # one more rotation, to be sure Relay_Log_Space is correctly updated @@ -83,7 +83,7 @@ drop table t1; save_master_pos; connection slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 0d447b8d1a3..da4d5f0bce1 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -31,14 +31,14 @@ system chmod 600 var/slave-data/master.info; # init_strvar_from_file() in init_master_info()). --error 1201 start slave; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT # CHANGE MASTER will fail because it first parses master.info before changing # it (so when master.info is bad, people have to use RESET SLAVE first). --error 1201 eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; reset slave; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; connection master; reset master; @@ -54,7 +54,7 @@ insert into temp_table values ("testing temporary tables"); create table t1 (s text); insert into t1 values('Could not break slave'),('Tried hard'); sync_slave_with_master; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; select * from t1; @@ -107,7 +107,7 @@ purge master logs before now(); show binary logs; insert into t2 values (65); sync_slave_with_master; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; select * from t2; @@ -139,7 +139,7 @@ connection slave; sync_with_master; select * from t4; ---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT +--replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # show slave status; # because of concurrent insert, the table may not be up to date diff --git a/mysql-test/t/rpl_server_id2.test b/mysql-test/t/rpl_server_id2.test index dc8f733b7ed..7bbac358ada 100644 --- a/mysql-test/t/rpl_server_id2.test +++ b/mysql-test/t/rpl_server_id2.test @@ -3,7 +3,6 @@ source include/master-slave.inc; connection slave; -drop table if exists t1; create table t1 (n int); reset master; # replicate ourselves diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 7d3b90aabeb..d3ddecfc314 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -31,6 +31,14 @@ select a from t1 order by a; select min(a) from t1; drop table t1; +create table t1 (c1 double, c2 varchar(20)); +insert t1 values (121,"16"); +select c1 + c1 * (c2 / 100) as col from t1; +create table t2 select c1 + c1 * (c2 / 100) as col from t1; +select * from t2; +show create table t2; +drop table t1,t2; + # Bug #1022: When a table contains a 'float' field, # and one of the functions MAX, MIN, or AVG is used on that field, # the system crashes. diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 3261ec309d4..da83e195943 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -224,6 +224,7 @@ $CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/* $CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r if [ $BASE_SYSTEM != "netware" ] ; then + chmod a+x $BASE/bin/* $CP scripts/* $BASE/bin $BASE/bin/replace \@localstatedir\@ ./data \@bindir\@ ./bin \@scriptdir\@ ./bin \@libexecdir\@ ./bin \@sbindir\@ ./bin \@prefix\@ . \@HOSTNAME\@ @HOSTNAME@ \@pkgdatadir\@ ./support-files < $SOURCE/scripts/mysql_install_db.sh > $BASE/scripts/mysql_install_db $BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index ff491a95043..8a40af90541 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -325,6 +325,35 @@ convert_error_code_to_mysql( } /***************************************************************** +If you want to print a thd that is not associated with the current thread, +you must call this function before reserving the InnoDB kernel_mutex, to +protect MySQL from setting thd->query NULL. If you print a thd of the current +thread, we know that MySQL cannot modify thd->query, and it is not necessary +to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release +the kernel_mutex. +NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this +function! */ +extern "C" +void +innobase_mysql_prepare_print_arbitrary_thd(void) +/*============================================*/ +{ + VOID(pthread_mutex_lock(&LOCK_thread_count)); +} + +/***************************************************************** +Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd(). +NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this +function! */ +extern "C" +void +innobase_mysql_end_print_arbitrary_thd(void) +/*========================================*/ +{ + VOID(pthread_mutex_unlock(&LOCK_thread_count)); +} + +/***************************************************************** Prints info of a THD object (== user session thread) to the standard output. NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for this function! */ @@ -335,9 +364,11 @@ innobase_mysql_print_thd( FILE* f, /* in: output stream */ void* input_thd)/* in: pointer to a MySQL THD object */ { - THD* thd; + const THD* thd; + const char* s; + char buf[301]; - thd = (THD*) input_thd; + thd = (const THD*) input_thd; fprintf(f, "MySQL thread id %lu, query id %lu", thd->thread_id, thd->query_id); @@ -356,14 +387,31 @@ innobase_mysql_print_thd( fputs(thd->user, f); } - if (thd->proc_info) { + if ((s = thd->proc_info)) { putc(' ', f); - fputs(thd->proc_info, f); + fputs(s, f); } - if (thd->query) { - putc(' ', f); - fputs(thd->query, f); + if ((s = thd->query)) { + /* determine the length of the query string */ + uint32 i, len; + + len = thd->query_length; + + if (len > 300) { + len = 300; /* ADDITIONAL SAFETY: print at most + 300 chars to reduce the probability of + a seg fault if there is a race in + thd->query_length in MySQL; after + May 14, 2004 probably no race any more, + but better be safe */ + } + + /* Use strmake to reduce the timeframe + for a race, compared to fwrite() */ + i= (uint) (strmake(buf, s, len) - buf); + putc('\n', f); + fwrite(buf, 1, i, f); } putc('\n', f); diff --git a/sql/item_func.cc b/sql/item_func.cc index aaea676fee1..f221e0dcc5c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -612,6 +612,7 @@ longlong Item_func_div::val_int() void Item_func_div::fix_length_and_dec() { decimals=max(args[0]->decimals,args[1]->decimals)+2; + set_if_smaller(decimals, NOT_FIXED_DEC); max_length=args[0]->max_length - args[0]->decimals + decimals; uint tmp=float_length(decimals); set_if_smaller(max_length,tmp); diff --git a/sql/log_event.cc b/sql/log_event.cc index b3ec1f0fe55..9cbcead743f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1058,6 +1058,7 @@ end: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db= 0; // prevent db from being freed thd->query= 0; // just to be sure + thd->query_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); // assume no convert for next query unless set explictly #ifdef TO_BE_REMOVED @@ -1674,6 +1675,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, thd->db= (char*) rewrite_db(db); DBUG_ASSERT(thd->query == 0); thd->query= 0; // Should not be needed + thd->querty_length= 0; // Should not be needed thd->query_error= 0; clear_all_errors(thd, rli); if (!use_rli_only_for_errors) diff --git a/sql/slave.cc b/sql/slave.cc index 12fec28ec49..4ce8d5939bc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3156,6 +3156,7 @@ err: IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety + thd->query_length = 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { @@ -3321,6 +3322,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ err: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety + thd->query_length = 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->proc_info = "Waiting for slave mutex on exit"; pthread_mutex_lock(&rli->run_lock); diff --git a/sql/sql_class.h b/sql/sql_class.h index e602b7d6d5f..2566385a6d9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -598,7 +598,24 @@ public: struct rand_struct rand; // used for authentication struct system_variables variables; // Changeable local variables pthread_mutex_t LOCK_delete; // Locked before thd is deleted - + /* + Note that (A) if we set query = NULL, we must at the same time set + query_length = 0, and protect the whole operation with the + LOCK_thread_count mutex. And (B) we are ONLY allowed to set query to a + non-NULL value if its previous value is NULL. We do not need to protect + operation (B) with any mutex. To avoid crashes in races, if we do not + know that thd->query cannot change at the moment, one should print + thd->query like this: + (1) reserve the LOCK_thread_count mutex; + (2) check if thd->query is NULL; + (3) if not NULL, then print at most thd->query_length characters from + it. We will see the query_length field as either 0, or the right value + for it. + Assuming that the write and read of an n-bit memory field in an n-bit + computer is atomic, we can avoid races in the above way. + This printing is needed at least in SHOW PROCESSLIST and SHOW INNODB + STATUS. + */ /* all prepared statements and cursors of this connection */ Statement_map stmt_map; /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e949d40625d..f2458068633 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1475,9 +1475,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, packet++; length--; } + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_length= length; thd->query= packet; - VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id= query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); #ifndef EMBEDDED_LIBRARY @@ -1768,6 +1768,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->proc_info=0; thd->command=COM_SLEEP; thd->query=0; + thd->query_length=0; thread_running--; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory @@ -1807,6 +1808,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) packet_length--; } /* We must allocate some extra memory for query cache */ + thd->query_length= 0; // Extra safety: Avoid races if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), packet_length, thd->db_length+ 1 + diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 51b44af63ec..80634c68ac7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1597,10 +1597,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->query=0; if (tmp->query) { - /* query_length is always set before tmp->query */ + /* + query_length is always set to 0 when we set query = NULL; see + the comment in sql_class.h why this prevents crashes in possible + races with query_length + */ uint length= min(max_query_length, tmp->query_length); - thd_info->query=(char*) thd->memdup(tmp->query,length+1); - thd_info->query[length]=0; + thd_info->query=(char*) thd->strmake(tmp->query,length); } thread_infos.append(thd_info); } |