149
159
#endif /* __i386__ && HAVE_FPU_CONTROL_H && _FPU_DOUBLE */
152
#include "drizzled/internal/my_pthread.h" // For thr_setconcurency()
154
#include <drizzled/gettext.h>
157
163
extern "C" int gethostname(char *name, int namelen);
161
using namespace drizzled;
166
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
167
static const char *optimizer_switch_names[]=
169
"no_materialization", "no_semijoin",
173
/* Corresponding defines are named OPTIMIZER_SWITCH_XXX */
174
static const unsigned int optimizer_switch_names_len[]=
176
/*no_materialization*/ 19,
180
TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
181
optimizer_switch_names,
182
(unsigned int *)optimizer_switch_names_len };
184
167
static const char *tc_heuristic_recover_names[]=
186
169
"COMMIT", "ROLLBACK", NULL
940
891
#define SA_NODEFER 0
943
static void init_signals(void)
948
if (!(test_flags.test(TEST_NO_STACKTRACE) ||
949
test_flags.test(TEST_CORE_ON_SIGNAL)))
951
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
952
sigemptyset(&sa.sa_mask);
953
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
956
sa.sa_handler=handle_segfault;
957
sigaction(SIGSEGV, &sa, NULL);
958
sigaction(SIGABRT, &sa, NULL);
960
sigaction(SIGBUS, &sa, NULL);
962
sigaction(SIGILL, &sa, NULL);
963
sigaction(SIGFPE, &sa, NULL);
966
if (test_flags.test(TEST_CORE_ON_SIGNAL))
968
/* Change limits so that we will get a core file */
970
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
971
if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
972
errmsg_printf(ERRMSG_LVL_WARN,
973
_("setrlimit could not change the size of core files "
974
"to 'infinity'; We may not be able to generate a "
975
"core file on signals"));
977
(void) sigemptyset(&set);
978
my_sigset(SIGPIPE,SIG_IGN);
979
sigaddset(&set,SIGPIPE);
980
#ifndef IGNORE_SIGHUP_SIGQUIT
981
sigaddset(&set,SIGQUIT);
982
sigaddset(&set,SIGHUP);
984
sigaddset(&set,SIGTERM);
986
/* Fix signals if blocked by parents (can happen on Mac OS X) */
987
sigemptyset(&sa.sa_mask);
989
sa.sa_handler = print_signal_warning;
990
sigaction(SIGTERM, &sa, (struct sigaction*) 0);
992
sa.sa_handler = print_signal_warning;
993
sigaction(SIGHUP, &sa, (struct sigaction*) 0);
995
sigaddset(&set,SIGTSTP);
997
if (test_flags.test(TEST_SIGINT))
999
my_sigset(thr_kill_signal, end_thread_signal);
1001
sigdelset(&set, thr_kill_signal);
1004
sigaddset(&set,SIGINT);
1005
sigprocmask(SIG_SETMASK,&set,NULL);
1006
pthread_sigmask(SIG_SETMASK,&set,NULL);
1010
void my_message_sql(uint32_t error, const char *str, myf MyFlags);
1013
896
All global error messages are sent here where the first one is stored
1016
void my_message_sql(uint32_t error, const char *str, myf MyFlags)
899
static void my_message_sql(uint32_t error, const char *str, myf MyFlags)
1018
901
Session *session;
1148
1031
{"show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
1149
1032
{"show_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
1150
1033
{"show_databases", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
1151
{"show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
1152
1034
{"show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
1153
1035
{"show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
1154
1036
{"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
1155
{"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
1156
1037
{"show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
1157
1038
{"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
1158
1039
{"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
1173
1054
{"Com", (char*) com_status_vars, SHOW_ARRAY},
1174
1055
{"Connections", (char*) &global_thread_id, SHOW_INT_NOFLUSH},
1175
1056
{"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
1176
{"Created_tmp_files", (char*) &my_tmp_file_created,SHOW_INT},
1057
{"Created_tmp_files", (char*) &internal::my_tmp_file_created,SHOW_INT},
1177
1058
{"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
1178
1059
{"Flush_commands", (char*) &refresh_version, SHOW_INT_NOFLUSH},
1179
1060
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
1199
1080
{"Key_writes", (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
1200
1081
{"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
1201
1082
{"Max_used_connections", (char*) &max_used_connections, SHOW_INT},
1202
{"Open_files", (char*) &my_file_opened, SHOW_INT_NOFLUSH},
1203
{"Open_streams", (char*) &my_stream_opened, SHOW_INT_NOFLUSH},
1083
{"Open_files", (char*) &internal::my_file_opened, SHOW_INT_NOFLUSH},
1084
{"Open_streams", (char*) &internal::my_stream_opened, SHOW_INT_NOFLUSH},
1204
1085
{"Open_table_definitions", (char*) &show_table_definitions_cont, SHOW_FUNC},
1205
1086
{"Open_tables", (char*) &show_open_tables_cont, SHOW_FUNC},
1206
{"Opened_files", (char*) &my_file_total_opened, SHOW_INT_NOFLUSH},
1087
{"Opened_files", (char*) &internal::my_file_total_opened, SHOW_INT_NOFLUSH},
1207
1088
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
1208
1089
{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
1209
1090
{"Questions", (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
1504
1385
unireg_abort(1);
1507
#if defined(MCL_CURRENT)
1508
if (locked_in_memory && !getuid())
1510
if (setreuid((uid_t)-1, 0) == -1)
1511
{ // this should never happen
1512
sql_perror("setreuid");
1515
if (mlockall(MCL_CURRENT))
1517
if (global_system_variables.log_warnings)
1518
errmsg_printf(ERRMSG_LVL_WARN, _("Failed to lock memory. Errno: %d\n"),errno);
1519
locked_in_memory= 0;
1522
set_user(drizzled_user, user_info);
1528
1388
init_update_queries();
1533
int main(int argc, char **argv)
1535
#if defined(ENABLE_NLS)
1536
# if defined(HAVE_LOCALE_H)
1537
setlocale(LC_ALL, "");
1539
bindtextdomain("drizzle", LOCALEDIR);
1540
textdomain("drizzle");
1543
plugin::Registry &plugins= plugin::Registry::singleton();
1544
plugin::Client *client;
1547
MY_INIT(argv[0]); // init my_sys library & pthreads
1548
/* nothing should come before this line ^^^ */
1550
/* Set signal used to kill Drizzle */
1551
#if defined(SIGUSR2)
1552
thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
1554
thr_kill_signal= SIGINT;
1557
if (init_common_variables(DRIZZLE_CONFIG_NAME,
1558
argc, argv, load_default_groups))
1559
unireg_abort(1); // Will do exit
1564
select_thread=pthread_self();
1565
select_thread_in_use=1;
1567
if (chdir(drizzle_real_data_home) && !opt_help)
1569
errmsg_printf(ERRMSG_LVL_ERROR, _("Data directory %s does not exist\n"), drizzle_real_data_home);
1572
drizzle_data_home= drizzle_data_home_buff;
1573
drizzle_data_home[0]=FN_CURLIB; // all paths are relative from here
1574
drizzle_data_home[1]=0;
1575
drizzle_data_home_len= 2;
1577
if ((user_info= check_user(drizzled_user)))
1579
#if defined(MCL_CURRENT)
1580
if (locked_in_memory) // getuid() == 0 here
1581
set_effective_user(user_info);
1584
set_user(drizzled_user, user_info);
1592
if (init_server_components(plugins))
1595
if (plugin::Listen::setup())
1599
init signals & alarm
1600
After this we can't quit by a simple unireg_abort
1602
error_handler_hook= my_message_sql;
1604
if (drizzle_rm_tmp_tables() ||
1605
my_tz_init((Session *)0, default_tz_name))
1608
select_thread_in_use=0;
1609
(void) pthread_kill(signal_thread, SIGTERM);
1611
(void) unlink(pidfile_name); // Not needed anymore
1618
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), my_progname,
1619
PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
1622
/* Listen for new connections and start new session for each connection
1623
accepted. The listen.getClient() method will return NULL when the server
1624
should be shutdown. */
1625
while ((client= plugin::Listen::getClient()) != NULL)
1627
if (!(session= new Session(client)))
1633
/* If we error on creation we drop the connection and delete the session. */
1634
if (session->schedule())
1635
Session::unlink(session);
1638
/* (void) pthread_attr_destroy(&connection_attrib); */
1641
(void) pthread_mutex_lock(&LOCK_thread_count);
1642
select_thread_in_use=0; // For close_connections
1643
(void) pthread_mutex_unlock(&LOCK_thread_count);
1644
(void) pthread_cond_broadcast(&COND_thread_count);
1646
/* Wait until cleanup is done */
1647
(void) pthread_mutex_lock(&LOCK_thread_count);
1648
while (!ready_to_exit)
1649
pthread_cond_wait(&COND_server_end,&LOCK_thread_count);
1650
(void) pthread_mutex_unlock(&LOCK_thread_count);
1653
plugin::Registry::shutdown();
1660
1394
/****************************************************************************
1661
1395
Handle start options
1662
1396
******************************************************************************/
1811
1546
(char**) &global_system_variables.log_warnings,
1812
1547
(char**) &max_system_variables.log_warnings, 0, GET_BOOL, OPT_ARG, 1, 0, 0,
1814
{"memlock", OPT_MEMLOCK,
1815
N_("Lock drizzled in memory."),
1816
(char**) &locked_in_memory,
1817
(char**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1818
1549
{"pid-file", OPT_PID_FILE,
1819
1550
N_("Pid file used by safe_mysqld."),
1820
1551
(char**) &pidfile_name_ptr, (char**) &pidfile_name_ptr, 0, GET_STR,
1981
1712
"[for example: --plugin_add=crc32,logger_gearman]"),
1982
1713
(char**) &opt_plugin_add, (char**) &opt_plugin_add, 0,
1983
1714
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1715
{"plugin_remove", OPT_PLUGIN_ADD,
1716
N_("Optional comma separated list of plugins to not load at startup. Effectively "
1717
"removes a plugin from the list of plugins to be loaded. "
1718
"[for example: --plugin_remove=crc32,logger_gearman]"),
1719
(char**) &opt_plugin_remove, (char**) &opt_plugin_remove, 0,
1720
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1984
1721
{"plugin_load", OPT_PLUGIN_LOAD,
1985
1722
N_("Optional comma separated list of plugins to load at starup instead of "
1986
1723
"the default plugin load list. "
2061
1798
(char**) &global_system_variables.tmp_table_size,
2062
1799
(char**) &max_system_variables.tmp_table_size, 0, GET_ULL,
2063
1800
REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
2064
{"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
2065
N_("Allocation block size for transactions to be stored in binary log"),
2066
(char**) &global_system_variables.trans_alloc_block_size,
2067
(char**) &max_system_variables.trans_alloc_block_size, 0, GET_UINT,
2068
REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
2069
{"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
2070
N_("Persistent buffer for transactions to be stored in binary log"),
2071
(char**) &global_system_variables.trans_prealloc_size,
2072
(char**) &max_system_variables.trans_prealloc_size, 0, GET_UINT,
2073
REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
2074
1801
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
2390
2114
static void fix_paths(string &progname)
2392
2116
char buff[FN_REFLEN],*pos,rp_buff[PATH_MAX];
2393
convert_dirname(drizzle_home,drizzle_home,NULL);
2117
internal::convert_dirname(drizzle_home,drizzle_home,NULL);
2394
2118
/* Resolve symlinks to allow 'drizzle_home' to be a relative symlink */
2395
2119
#if defined(HAVE_BROKEN_REALPATH)
2396
my_load_path(drizzle_home, drizzle_home, NULL);
2120
internal::my_load_path(drizzle_home, drizzle_home, NULL);
2398
2122
if (!realpath(drizzle_home,rp_buff))
2399
my_load_path(rp_buff, drizzle_home, NULL);
2123
internal::my_load_path(rp_buff, drizzle_home, NULL);
2400
2124
rp_buff[FN_REFLEN-1]= '\0';
2401
2125
strcpy(drizzle_home,rp_buff);
2402
2126
/* Ensure that drizzle_home ends in FN_LIBCHAR */
2407
2131
pos[0]= FN_LIBCHAR;
2410
convert_dirname(drizzle_real_data_home,drizzle_real_data_home,NULL);
2411
(void) fn_format(buff, drizzle_real_data_home, "", "",
2134
internal::convert_dirname(drizzle_real_data_home,drizzle_real_data_home,NULL);
2135
(void) internal::fn_format(buff, drizzle_real_data_home, "", "",
2412
2136
(MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
2413
(void) unpack_dirname(drizzle_unpacked_real_data_home, buff);
2414
convert_dirname(language,language,NULL);
2415
(void) my_load_path(drizzle_home, drizzle_home,""); // Resolve current dir
2416
(void) my_load_path(drizzle_real_data_home, drizzle_real_data_home,drizzle_home);
2417
(void) my_load_path(pidfile_name, pidfile_name,drizzle_real_data_home);
2137
(void) internal::unpack_dirname(drizzle_unpacked_real_data_home, buff);
2138
internal::convert_dirname(language,language,NULL);
2139
(void) internal::my_load_path(drizzle_home, drizzle_home,""); // Resolve current dir
2140
(void) internal::my_load_path(drizzle_real_data_home, drizzle_real_data_home,drizzle_home);
2141
(void) internal::my_load_path(pidfile_name, pidfile_name,drizzle_real_data_home);
2419
2143
if (opt_plugin_dir_ptr == NULL)
2458
2182
size_t last_libchar_pos= progdir.rfind(FN_LIBCHAR,progdir.size()-2)+1;
2459
2183
string source_plugindir(progdir.substr(0,last_libchar_pos));
2460
2184
source_plugindir.append("plugin/.libs");
2461
(void) my_load_path(opt_plugin_dir, source_plugindir.c_str(), "");
2185
(void) internal::my_load_path(opt_plugin_dir, source_plugindir.c_str(), "");
2466
(void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr, drizzle_home);
2190
(void) internal::my_load_path(opt_plugin_dir, opt_plugin_dir_ptr, drizzle_home);
2468
2192
opt_plugin_dir_ptr= opt_plugin_dir;
2470
2194
const char *sharedir= get_relative_path(PKGDATADIR);
2471
if (test_if_hard_path(sharedir))
2195
if (internal::test_if_hard_path(sharedir))
2472
2196
strncpy(buff,sharedir,sizeof(buff)-1);
2475
2199
strcpy(buff, drizzle_home);
2476
2200
strncat(buff, sharedir, sizeof(buff)-strlen(drizzle_home)-1);
2478
convert_dirname(buff,buff,NULL);
2479
(void) my_load_path(language,language,buff);
2202
internal::convert_dirname(buff,buff,NULL);
2203
(void) internal::my_load_path(language,language,buff);
2482
2206
char *tmp_string;
2240
} /* namespace drizzled */
2242
using namespace drizzled;
2245
static void init_signals(void)
2248
struct sigaction sa;
2250
if (!(test_flags.test(TEST_NO_STACKTRACE) ||
2251
test_flags.test(TEST_CORE_ON_SIGNAL)))
2253
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
2254
sigemptyset(&sa.sa_mask);
2255
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
2258
sa.sa_handler=handle_segfault;
2259
sigaction(SIGSEGV, &sa, NULL);
2260
sigaction(SIGABRT, &sa, NULL);
2262
sigaction(SIGBUS, &sa, NULL);
2264
sigaction(SIGILL, &sa, NULL);
2265
sigaction(SIGFPE, &sa, NULL);
2268
if (test_flags.test(TEST_CORE_ON_SIGNAL))
2270
/* Change limits so that we will get a core file */
2272
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
2273
if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
2274
errmsg_printf(ERRMSG_LVL_WARN,
2275
_("setrlimit could not change the size of core files "
2276
"to 'infinity'; We may not be able to generate a "
2277
"core file on signals"));
2279
(void) sigemptyset(&set);
2280
my_sigset(SIGPIPE,SIG_IGN);
2281
sigaddset(&set,SIGPIPE);
2282
#ifndef IGNORE_SIGHUP_SIGQUIT
2283
sigaddset(&set,SIGQUIT);
2284
sigaddset(&set,SIGHUP);
2286
sigaddset(&set,SIGTERM);
2288
/* Fix signals if blocked by parents (can happen on Mac OS X) */
2289
sigemptyset(&sa.sa_mask);
2291
sa.sa_handler = print_signal_warning;
2292
sigaction(SIGTERM, &sa, (struct sigaction*) 0);
2294
sa.sa_handler = print_signal_warning;
2295
sigaction(SIGHUP, &sa, (struct sigaction*) 0);
2297
sigaddset(&set,SIGTSTP);
2299
if (test_flags.test(TEST_SIGINT))
2301
my_sigset(thr_kill_signal, end_thread_signal);
2303
sigdelset(&set, thr_kill_signal);
2306
sigaddset(&set,SIGINT);
2307
sigprocmask(SIG_SETMASK,&set,NULL);
2308
pthread_sigmask(SIG_SETMASK,&set,NULL);
2312
int main(int argc, char **argv)
2314
#if defined(ENABLE_NLS)
2315
# if defined(HAVE_LOCALE_H)
2316
setlocale(LC_ALL, "");
2318
bindtextdomain("drizzle", LOCALEDIR);
2319
textdomain("drizzle");
2322
plugin::Registry &plugins= plugin::Registry::singleton();
2323
plugin::Client *client;
2326
MY_INIT(argv[0]); // init my_sys library & pthreads
2327
/* nothing should come before this line ^^^ */
2329
/* Set signal used to kill Drizzle */
2330
#if defined(SIGUSR2)
2331
thr_kill_signal= internal::thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
2333
thr_kill_signal= SIGINT;
2336
if (init_common_variables(DRIZZLE_CONFIG_NAME,
2337
argc, argv, load_default_groups))
2338
unireg_abort(1); // Will do exit
2343
select_thread=pthread_self();
2344
select_thread_in_use=1;
2346
if (chdir(drizzle_real_data_home) && !opt_help)
2348
errmsg_printf(ERRMSG_LVL_ERROR, _("Data directory %s does not exist\n"), drizzle_real_data_home);
2351
drizzle_data_home= drizzle_data_home_buff;
2352
drizzle_data_home[0]=FN_CURLIB; // all paths are relative from here
2353
drizzle_data_home[1]=0;
2354
drizzle_data_home_len= 2;
2356
if ((user_info= check_user(drizzled_user)))
2358
set_user(drizzled_user, user_info);
2366
if (init_server_components(plugins))
2369
if (plugin::Listen::setup())
2373
init signals & alarm
2374
After this we can't quit by a simple unireg_abort
2376
error_handler_hook= my_message_sql;
2378
if (drizzle_rm_tmp_tables() ||
2379
my_tz_init((Session *)0, default_tz_name))
2382
select_thread_in_use=0;
2383
(void) pthread_kill(signal_thread, SIGTERM);
2385
(void) unlink(pidfile_name); // Not needed anymore
2392
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), internal::my_progname,
2393
PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
2396
/* Listen for new connections and start new session for each connection
2397
accepted. The listen.getClient() method will return NULL when the server
2398
should be shutdown. */
2399
while ((client= plugin::Listen::getClient()) != NULL)
2401
if (!(session= new Session(client)))
2407
/* If we error on creation we drop the connection and delete the session. */
2408
if (session->schedule())
2409
Session::unlink(session);
2412
/* (void) pthread_attr_destroy(&connection_attrib); */
2415
(void) pthread_mutex_lock(&LOCK_thread_count);
2416
select_thread_in_use=0; // For close_connections
2417
(void) pthread_mutex_unlock(&LOCK_thread_count);
2418
(void) pthread_cond_broadcast(&COND_thread_count);
2420
/* Wait until cleanup is done */
2421
(void) pthread_mutex_lock(&LOCK_thread_count);
2422
while (!ready_to_exit)
2423
pthread_cond_wait(&COND_server_end,&LOCK_thread_count);
2424
(void) pthread_mutex_unlock(&LOCK_thread_count);
2427
plugin::Registry::shutdown();