#At file:///export/home/tmp/ss156133/z/45058-51/ based on revid:alik@stripped
3120 Staale Smedseng 2009-09-11
Bug #45058 init_available_charsets uses double checked locking
As documented in the bug report, the double checked locking
pattern has inherent issues, and cannot guarantee correct
initialization.
This patch modifies the charset initialization code to do its
work during server/client initialization, and not through
calls to get_charset_*(). This is achieved by splitting
init_available_charsets() into two functions:
* load_compiled_charsets(): loads the compiled character
sets, called from my_init(),
* load_available_charsets(): loads charset index file after
any options regarding charset directory have been
processed; called explicitly in mysqld.cc, mysqldump.cc
a.o., and implicitly in clients through
mysql_library_init().
The split is necessary to support functions relying on
charsets that are used early on, while giving the possibility
of changing the source charsets_dir (e.g., during options
parsing) before loading charset definitions.
@ client/mysqldump.c
Adding explicit loading of charset info from file.
@ extra/charset2html.c
Adding explicit loading of charset info from file.
@ extra/comp_err.c
Adding explicit loading of charset info from file.
@ include/my_sys.h
init_available_charsets() is split into two functions.
@ libmysql/libmysql.c
Adding explicit loading of charset info from file.
@ mysys/charset.c
init_available_charsets() is split into two functions. Calls
to init_available_charsets() are dropped from the get_charset*() functions.
@ mysys/my_init.c
Adding explicit loading of compiled charsets in my_init().
@ netware/libmysqlmain.c
Charset loading now happens in my_init() and mysql_server_init().
@ sql/mysqld.cc
Adding explicit loading of charset info from file.
modified:
client/mysqldump.c
extra/charset2html.c
extra/comp_err.c
include/my_sys.h
libmysql/libmysql.c
mysys/charset.c
mysys/my_init.c
netware/libmysqlmain.c
sql/mysqld.cc
=== modified file 'client/mysqldump.c'
--- a/client/mysqldump.c 2009-08-28 15:06:59 +0000
+++ b/client/mysqldump.c 2009-09-11 17:24:20 +0000
@@ -921,6 +921,7 @@ static int get_options(int *argc, char *
my_progname);
return(EX_USAGE);
}
+ load_available_charsets(MYF(0));
if (strcmp(default_charset, charset_info->csname) &&
!(charset_info= get_charset_by_csname(default_charset,
MY_CS_PRIMARY, MYF(MY_WME))))
=== modified file 'extra/charset2html.c'
--- a/extra/charset2html.c 2008-03-29 14:15:06 +0000
+++ b/extra/charset2html.c 2009-09-11 17:24:20 +0000
@@ -120,8 +120,6 @@ static void print_index()
CHARSET_INFO **cs;
int clr=0;
- get_charset_by_name("",MYF(0)); /* To execute init_available_charsets */
-
printf("All charsets\n");
printf("<table border=1>\n");
printf("<tr bgcolor=EEEE99><th>ID<th>Charset<th>Collation<th>Def<th>Bin<th>Com<th>Comment\n");
@@ -162,7 +160,8 @@ int main(int argc, char **argv) {
if (argc > argcnt)
charsets_dir = argv[argcnt++];
-
+ load_available_charsets(MYF(0));
+
if (!the_set)
{
print_index();
=== modified file 'extra/comp_err.c'
--- a/extra/comp_err.c 2009-02-13 16:41:47 +0000
+++ b/extra/comp_err.c 2009-09-11 17:24:20 +0000
@@ -167,6 +167,7 @@ int main(int argc, char *argv[])
DBUG_ENTER("main");
charsets_dir= DEFAULT_CHARSET_DIR;
+ load_available_charsets(MYF(0));
my_umask_dir= 0777;
if (get_options(&argc, &argv))
DBUG_RETURN(1);
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2009-09-03 12:29:25 +0000
+++ b/include/my_sys.h 2009-09-11 17:24:20 +0000
@@ -926,6 +926,8 @@ int my_getpagesize(void);
int my_msync(int, void *, size_t, int);
/* character sets */
+extern void load_compiled_charsets(myf myflags);
+extern my_bool load_available_charsets(myf myflags);
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
extern const char *get_charset_name(uint cs_number);
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2009-08-28 16:21:54 +0000
+++ b/libmysql/libmysql.c 2009-09-11 17:24:20 +0000
@@ -125,6 +125,7 @@ int STDCALL mysql_server_init(int argc _
org_my_init_done=my_init_done;
if (my_init()) /* Will init threads */
return 1;
+ load_available_charsets(MYF(0));
init_client_errs();
if (!mysql_port)
{
=== modified file 'mysys/charset.c'
--- a/mysys/charset.c 2009-06-10 08:59:49 +0000
+++ b/mysys/charset.c 2009-09-11 17:24:20 +0000
@@ -321,7 +321,6 @@ static int add_collation(CHARSET_INFO *c
#define MY_CHARSET_INDEX "Index.xml"
const char *charsets_dir= NULL;
-static int charset_initialized=0;
static my_bool my_read_charset_file(const char *filename, myf myflags)
@@ -399,63 +398,50 @@ static void *cs_alloc(size_t size)
}
-#ifdef __NETWARE__
-my_bool STDCALL init_available_charsets(myf myflags)
-#else
-static my_bool init_available_charsets(myf myflags)
-#endif
+/* Initialization part 1: Load the compiled charsets. */
+void load_compiled_charsets(myf myflags)
{
- char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
- my_bool error=FALSE;
- /*
- We have to use charset_initialized to not lock on THR_LOCK_charset
- inside get_internal_charset...
- */
- if (!charset_initialized)
+ CHARSET_INFO **cs;
+
+ bzero(&all_charsets,sizeof(all_charsets));
+ init_compiled_charsets(myflags);
+
+ /* Copy compiled charsets */
+ for (cs=all_charsets;
+ cs < all_charsets+array_elements(all_charsets)-1 ;
+ cs++)
{
- CHARSET_INFO **cs;
- /*
- To make things thread safe we are not allowing other threads to interfere
- while we may changing the cs_info_table
- */
- pthread_mutex_lock(&THR_LOCK_charset);
- if (!charset_initialized)
+ if (*cs)
{
- bzero(&all_charsets,sizeof(all_charsets));
- init_compiled_charsets(myflags);
-
- /* Copy compiled charsets */
- for (cs=all_charsets;
- cs < all_charsets+array_elements(all_charsets)-1 ;
- cs++)
- {
- if (*cs)
- {
- if (cs[0]->ctype)
- if (init_state_maps(*cs))
- *cs= NULL;
- }
- }
-
- strmov(get_charsets_dir(fname), MY_CHARSET_INDEX);
- error= my_read_charset_file(fname,myflags);
- charset_initialized=1;
+ if (cs[0]->ctype)
+ if (init_state_maps(*cs))
+ *cs= NULL;
}
- pthread_mutex_unlock(&THR_LOCK_charset);
}
- return error;
+
+ return FALSE;
+}
+
+
+/*
+ Initialization part 2: Load the Index file from the charsets_dir directory.
+*/
+my_bool load_available_charsets(myf myflags)
+{
+ char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
+
+ strmov(get_charsets_dir(fname), MY_CHARSET_INDEX);
+ return my_read_charset_file(fname,myflags);
}
void free_charsets(void)
{
- charset_initialized=0;
}
uint get_collation_number(const char *name)
{
- init_available_charsets(MYF(0));
return get_collation_number_internal(name);
}
@@ -463,7 +449,6 @@ uint get_collation_number(const char *na
uint get_charset_number(const char *charset_name, uint cs_flags)
{
CHARSET_INFO **cs;
- init_available_charsets(MYF(0));
for (cs= all_charsets;
cs < all_charsets+array_elements(all_charsets)-1 ;
@@ -480,7 +465,6 @@ uint get_charset_number(const char *char
const char *get_charset_name(uint charset_number)
{
CHARSET_INFO *cs;
- init_available_charsets(MYF(0));
cs=all_charsets[charset_number];
if (cs && (cs->number == charset_number) && cs->name )
@@ -538,8 +522,6 @@ CHARSET_INFO *get_charset(uint cs_number
if (cs_number == default_charset_info->number)
return default_charset_info;
- (void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
if (!cs_number || cs_number >= array_elements(all_charsets)-1)
return NULL;
@@ -560,7 +542,6 @@ CHARSET_INFO *get_charset_by_name(const
{
uint cs_number;
CHARSET_INFO *cs;
- (void) init_available_charsets(MYF(0)); /* If it isn't initialized */
cs_number=get_collation_number(cs_name);
cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
@@ -585,8 +566,6 @@ CHARSET_INFO *get_charset_by_csname(cons
DBUG_ENTER("get_charset_by_csname");
DBUG_PRINT("enter",("name: '%s'", cs_name));
- (void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
cs_number= get_charset_number(cs_name, cs_flags);
cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
=== modified file 'mysys/my_init.c'
--- a/mysys/my_init.c 2009-07-10 23:12:13 +0000
+++ b/mysys/my_init.c 2009-09-11 17:24:20 +0000
@@ -77,6 +77,7 @@ my_bool my_init(void)
my_umask= 0660; /* Default umask for new files */
my_umask_dir= 0700; /* Default umask for new directories */
init_glob_errs();
+ load_compiled_charsets(MYF(0));
#if defined(THREAD)
if (my_thread_global_init())
return 1;
=== modified file 'netware/libmysqlmain.c'
--- a/netware/libmysqlmain.c 2003-01-31 23:42:26 +0000
+++ b/netware/libmysqlmain.c 2009-09-11 17:24:20 +0000
@@ -30,8 +30,6 @@ int _NonAppStart(void *NLMHandle, void *
const char **messages)
{
mysql_server_init(0, NULL, NULL);
-
- init_available_charsets(MYF(0));
return 0;
}
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2009-09-10 07:40:57 +0000
+++ b/sql/mysqld.cc 2009-09-11 17:24:20 +0000
@@ -3268,6 +3268,7 @@ static int init_common_variables(const c
defaults_argc=argc;
if (get_options(&defaults_argc, defaults_argv))
return 1;
+ load_available_charsets(MYF(0));
set_server_version();
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
Attachment: [text/bzr-bundle] bzr/staale.smedseng@sun.com-20090911172420-4ypxcjyuisigv626.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-bugteam branch (staale.smedseng:3120) Bug#45058 | Staale Smedseng | 11 Sep |