Fix rare issue with static initialization

ycmd would sometimes crash on startup with a coredump and a message from glibc
on how free() was called for an invalid pointer. A gdb session pointed out that
the problem was with static initialization order.
This commit is contained in:
Strahinja Val Markovic 2013-10-25 13:03:00 -07:00
parent 77b8adf0a9
commit f20448d89e

View File

@ -65,53 +65,70 @@ const char *TAG_REGEX =
"language:([^\\t\\n\\r]+)" // We want to capture the language of the file "language:([^\\t\\n\\r]+)" // We want to capture the language of the file
".*?$"; ".*?$";
// Only used as the equality comparer for the below unordered_map which stores
// const char* pointers and not std::string but needs to hash based on string
// values and not pointer values.
// When passed a const char* this will create a temporary std::string for
// comparison, but it's fast enough for our use case.
struct StringEqualityComparer :
std::binary_function< std::string, std::string, bool >
{
bool operator()( const std::string &a, const std::string &b ) const {
return a == b;
}
};
// List of languages Exuberant Ctags supports: // List of languages Exuberant Ctags supports:
// ctags --list-languages // ctags --list-languages
// To map a language name to a filetype, see this file: // To map a language name to a filetype, see this file:
// :e $VIMRUNTIME/filetype.vim // :e $VIMRUNTIME/filetype.vim
const boost::unordered_map< std::string, std::string > LANG_TO_FILETYPE = // This is a map of const char* and not std::string to prevent issues with
// static initialization.
const boost::unordered_map< const char*,
const char*,
boost::hash< std::string >,
StringEqualityComparer > LANG_TO_FILETYPE =
boost::assign::map_list_of boost::assign::map_list_of
( std::string( "Ant" ), std::string( "ant" ) ) ( "Ant" , "ant" )
( std::string( "Asm" ), std::string( "asm" ) ) ( "Asm" , "asm" )
( std::string( "Awk" ), std::string( "awk" ) ) ( "Awk" , "awk" )
( std::string( "Basic" ), std::string( "basic" ) ) ( "Basic" , "basic" )
( std::string( "C++" ), std::string( "cpp" ) ) ( "C++" , "cpp" )
( std::string( "C#" ), std::string( "cs" ) ) ( "C#" , "cs" )
( std::string( "C" ), std::string( "c" ) ) ( "C" , "c" )
( std::string( "COBOL" ), std::string( "cobol" ) ) ( "COBOL" , "cobol" )
( std::string( "DosBatch" ), std::string( "dosbatch" ) ) ( "DosBatch" , "dosbatch" )
( std::string( "Eiffel" ), std::string( "eiffel" ) ) ( "Eiffel" , "eiffel" )
( std::string( "Erlang" ), std::string( "erlang" ) ) ( "Erlang" , "erlang" )
( std::string( "Fortran" ), std::string( "fortran" ) ) ( "Fortran" , "fortran" )
( std::string( "HTML" ), std::string( "html" ) ) ( "HTML" , "html" )
( std::string( "Java" ), std::string( "java" ) ) ( "Java" , "java" )
( std::string( "JavaScript" ), std::string( "javascript" ) ) ( "JavaScript" , "javascript" )
( std::string( "Lisp" ), std::string( "lisp" ) ) ( "Lisp" , "lisp" )
( std::string( "Lua" ), std::string( "lua" ) ) ( "Lua" , "lua" )
( std::string( "Make" ), std::string( "make" ) ) ( "Make" , "make" )
( std::string( "MatLab" ), std::string( "matlab" ) ) ( "MatLab" , "matlab" )
( std::string( "OCaml" ), std::string( "ocaml" ) ) ( "OCaml" , "ocaml" )
( std::string( "Pascal" ), std::string( "pascal" ) ) ( "Pascal" , "pascal" )
( std::string( "Perl" ), std::string( "perl" ) ) ( "Perl" , "perl" )
( std::string( "PHP" ), std::string( "php" ) ) ( "PHP" , "php" )
( std::string( "Python" ), std::string( "python" ) ) ( "Python" , "python" )
( std::string( "REXX" ), std::string( "rexx" ) ) ( "REXX" , "rexx" )
( std::string( "Ruby" ), std::string( "ruby" ) ) ( "Ruby" , "ruby" )
( std::string( "Scheme" ), std::string( "scheme" ) ) ( "Scheme" , "scheme" )
( std::string( "Sh" ), std::string( "sh" ) ) ( "Sh" , "sh" )
( std::string( "SLang" ), std::string( "slang" ) ) ( "SLang" , "slang" )
( std::string( "SML" ), std::string( "sml" ) ) ( "SML" , "sml" )
( std::string( "SQL" ), std::string( "sql" ) ) ( "SQL" , "sql" )
( std::string( "Tcl" ), std::string( "tcl" ) ) ( "Tcl" , "tcl" )
( std::string( "Tex" ), std::string( "tex" ) ) ( "Tex" , "tex" )
( std::string( "Vera" ), std::string( "vera" ) ) ( "Vera" , "vera" )
( std::string( "Verilog" ), std::string( "verilog" ) ) ( "Verilog" , "verilog" )
( std::string( "VHDL" ), std::string( "vhdl" ) ) ( "VHDL" , "vhdl" )
( std::string( "Vim" ), std::string( "vim" ) ) ( "Vim" , "vim" )
( std::string( "YACC" ), std::string( "yacc" ) ); ( "YACC" , "yacc" );
const std::string NOT_FOUND = "YCMFOOBAR_NOT_FOUND"; const char* NOT_FOUND = "YCMFOOBAR_NOT_FOUND";
} // unnamed namespace } // unnamed namespace
@ -164,7 +181,7 @@ FiletypeIdentifierMap ExtractIdentifiersFromTagsFile(
std::string language( matches[ 3 ] ); std::string language( matches[ 3 ] );
std::string filetype = FindWithDefault( LANG_TO_FILETYPE, std::string filetype = FindWithDefault( LANG_TO_FILETYPE,
language, language.c_str(),
NOT_FOUND ); NOT_FOUND );
if ( filetype == NOT_FOUND ) if ( filetype == NOT_FOUND )