Commit 4a325159 authored by Jan Lindström's avatar Jan Lindström

MDEV-7403: should not pass recv_writer_thread_handle to CloseHandle()

Analysis: For some reason actual thread handle is not
returned on Windows instead lpThreadId was returned and
thread handle was closed after thread create. Later
CloseHandle was called for recv_writer_thread_handle
and psort_info->thread_hdl.

Fix: Return thread handle from os_thread_create()
also on Windows and store these thread handles also
in srv0start.cc so that they can be later closed.
parent 6e0a00ed
...@@ -132,10 +132,8 @@ os_thread_create_func( ...@@ -132,10 +132,8 @@ os_thread_create_func(
if (thread_id) { if (thread_id) {
*thread_id = win_thread_id; *thread_id = win_thread_id;
} }
if (thread) {
CloseHandle(thread); return((os_thread_t)thread);
}
return((os_thread_t)win_thread_id);
#else #else
int ret; int ret;
os_thread_t pthread; os_thread_t pthread;
......
...@@ -131,6 +131,17 @@ static ulint n[SRV_MAX_N_IO_THREADS + 6]; ...@@ -131,6 +131,17 @@ static ulint n[SRV_MAX_N_IO_THREADS + 6];
/** io_handler_thread identifiers, 32 is the maximum number of purge threads */ /** io_handler_thread identifiers, 32 is the maximum number of purge threads */
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 32]; static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 32];
/** Thead handles */
static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 6 + 32];
static os_thread_t buf_flush_page_cleaner_thread_handle;
static os_thread_t buf_dump_thread_handle;
static os_thread_t dict_stats_thread_handle;
/** Status variables, is thread started ?*/
static bool thread_started[SRV_MAX_N_IO_THREADS + 6 + 32] = {false};
static bool buf_flush_page_cleaner_thread_started = false;
static bool buf_dump_thread_started = false;
static bool dict_stats_thread_started = false;
/** We use this mutex to test the return value of pthread_mutex_trylock /** We use this mutex to test the return value of pthread_mutex_trylock
on successful locking. HP-UX does NOT return 0, though Linux et al do. */ on successful locking. HP-UX does NOT return 0, though Linux et al do. */
static os_fast_mutex_t srv_os_test_mutex; static os_fast_mutex_t srv_os_test_mutex;
...@@ -1983,7 +1994,8 @@ innobase_start_or_create_for_mysql(void) ...@@ -1983,7 +1994,8 @@ innobase_start_or_create_for_mysql(void)
n[i] = i; n[i] = i;
os_thread_create(io_handler_thread, n + i, thread_ids + i); thread_handles[i] = os_thread_create(io_handler_thread, n + i, thread_ids + i);
thread_started[i] = true;
} }
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
...@@ -2647,19 +2659,22 @@ innobase_start_or_create_for_mysql(void) ...@@ -2647,19 +2659,22 @@ innobase_start_or_create_for_mysql(void)
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
/* Create the thread which watches the timeouts /* Create the thread which watches the timeouts
for lock waits */ for lock waits */
os_thread_create( thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create(
lock_wait_timeout_thread, lock_wait_timeout_thread,
NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS);
thread_started[2 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which warns of long semaphore waits */ /* Create the thread which warns of long semaphore waits */
os_thread_create( thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_error_monitor_thread, srv_error_monitor_thread,
NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS);
thread_started[3 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which prints InnoDB monitor info */ /* Create the thread which prints InnoDB monitor info */
os_thread_create( thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_monitor_thread, srv_monitor_thread,
NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
thread_started[4 + SRV_MAX_N_IO_THREADS] = true;
} }
/* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */ /* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */
...@@ -2686,26 +2701,30 @@ innobase_start_or_create_for_mysql(void) ...@@ -2686,26 +2701,30 @@ innobase_start_or_create_for_mysql(void)
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
os_thread_create( thread_handles[1 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_master_thread, srv_master_thread,
NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS)); NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
thread_started[1 + SRV_MAX_N_IO_THREADS] = true;
} }
if (!srv_read_only_mode if (!srv_read_only_mode
&& srv_force_recovery < SRV_FORCE_NO_BACKGROUND) { && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
os_thread_create( thread_handles[5 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_purge_coordinator_thread, srv_purge_coordinator_thread,
NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS);
thread_started[5 + SRV_MAX_N_IO_THREADS] = true;
ut_a(UT_ARR_SIZE(thread_ids) ut_a(UT_ARR_SIZE(thread_ids)
> 5 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS); > 5 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS);
/* We've already created the purge coordinator thread above. */ /* We've already created the purge coordinator thread above. */
for (i = 1; i < srv_n_purge_threads; ++i) { for (i = 1; i < srv_n_purge_threads; ++i) {
os_thread_create( thread_handles[5 + i + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_worker_thread, NULL, srv_worker_thread, NULL,
thread_ids + 5 + i + SRV_MAX_N_IO_THREADS); thread_ids + 5 + i + SRV_MAX_N_IO_THREADS);
thread_started[5 + i + SRV_MAX_N_IO_THREADS] = true;
} }
srv_start_wait_for_purge_to_start(); srv_start_wait_for_purge_to_start();
...@@ -2715,7 +2734,8 @@ innobase_start_or_create_for_mysql(void) ...@@ -2715,7 +2734,8 @@ innobase_start_or_create_for_mysql(void)
} }
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL); buf_flush_page_cleaner_thread_handle = os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL);
buf_flush_page_cleaner_thread_started = true;
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -2860,10 +2880,12 @@ innobase_start_or_create_for_mysql(void) ...@@ -2860,10 +2880,12 @@ innobase_start_or_create_for_mysql(void)
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
/* Create the buffer pool dump/load thread */ /* Create the buffer pool dump/load thread */
os_thread_create(buf_dump_thread, NULL, NULL); buf_dump_thread_handle = os_thread_create(buf_dump_thread, NULL, NULL);
buf_dump_thread_started = true;
/* Create the dict stats gathering thread */ /* Create the dict stats gathering thread */
os_thread_create(dict_stats_thread, NULL, NULL); dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL);
dict_stats_thread_started = true;
/* Create the thread that will optimize the FTS sub-system. */ /* Create the thread that will optimize the FTS sub-system. */
fts_optimize_init(); fts_optimize_init();
...@@ -3032,6 +3054,34 @@ innobase_shutdown_for_mysql(void) ...@@ -3032,6 +3054,34 @@ innobase_shutdown_for_mysql(void)
dict_stats_thread_deinit(); dict_stats_thread_deinit();
} }
#ifdef __WIN__
/* MDEV-361: ha_innodb.dll leaks handles on Windows
MDEV-7403: should not pass recv_writer_thread_handle to
CloseHandle().
On Windows we should call CloseHandle() for all
open thread handles. */
if (os_thread_count == 0) {
for (i = 0; i < SRV_MAX_N_IO_THREADS + 6 + 32; ++i) {
if (thread_started[i]) {
CloseHandle(thread_handles[i]);
}
}
if (buf_flush_page_cleaner_thread_started) {
CloseHandle(buf_flush_page_cleaner_thread_handle);
}
if (buf_dump_thread_started) {
CloseHandle(buf_dump_thread_handle);
}
if (dict_stats_thread_started) {
CloseHandle(dict_stats_thread_handle);
}
}
#endif /* __WIN __ */
/* This must be disabled before closing the buffer pool /* This must be disabled before closing the buffer pool
and closing the data dictionary. */ and closing the data dictionary. */
btr_search_disable(); btr_search_disable();
......
...@@ -156,10 +156,8 @@ os_thread_create_func( ...@@ -156,10 +156,8 @@ os_thread_create_func(
if (thread_id) { if (thread_id) {
*thread_id = win_thread_id; *thread_id = win_thread_id;
} }
if (thread) {
CloseHandle(thread); return((os_thread_t)thread);
}
return((os_thread_t)win_thread_id);
#else #else
int ret; int ret;
os_thread_t pthread; os_thread_t pthread;
......
...@@ -134,6 +134,21 @@ static ulint n[SRV_MAX_N_IO_THREADS + 6]; ...@@ -134,6 +134,21 @@ static ulint n[SRV_MAX_N_IO_THREADS + 6];
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6
+ SRV_MAX_N_PURGE_THREADS]; + SRV_MAX_N_PURGE_THREADS];
/** Thead handles */
static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 6 + SRV_MAX_N_PURGE_THREADS];
static os_thread_t buf_flush_page_cleaner_thread_handle;
static os_thread_t buf_dump_thread_handle;
static os_thread_t dict_stats_thread_handle;
static os_thread_t buf_flush_lru_manager_thread_handle;
static os_thread_t srv_redo_log_follow_thread_handle;
/** Status variables, is thread started ?*/
static bool thread_started[SRV_MAX_N_IO_THREADS + 6 + SRV_MAX_N_PURGE_THREADS] = {false};
static bool buf_flush_page_cleaner_thread_started = false;
static bool buf_dump_thread_started = false;
static bool dict_stats_thread_started = false;
static bool buf_flush_lru_manager_thread_started = false;
static bool srv_redo_log_follow_thread_started = false;
/** We use this mutex to test the return value of pthread_mutex_trylock /** We use this mutex to test the return value of pthread_mutex_trylock
on successful locking. HP-UX does NOT return 0, though Linux et al do. */ on successful locking. HP-UX does NOT return 0, though Linux et al do. */
static os_fast_mutex_t srv_os_test_mutex; static os_fast_mutex_t srv_os_test_mutex;
...@@ -1532,8 +1547,9 @@ init_log_online(void) ...@@ -1532,8 +1547,9 @@ init_log_online(void)
/* Create the thread that follows the redo log to output the /* Create the thread that follows the redo log to output the
changed page bitmap */ changed page bitmap */
os_thread_create(&srv_redo_log_follow_thread, NULL, srv_redo_log_follow_thread_handle = os_thread_create(&srv_redo_log_follow_thread, NULL,
thread_ids + 5 + SRV_MAX_N_IO_THREADS); thread_ids + 5 + SRV_MAX_N_IO_THREADS);
srv_redo_log_follow_thread_started = true;
} }
} }
...@@ -2059,7 +2075,8 @@ innobase_start_or_create_for_mysql(void) ...@@ -2059,7 +2075,8 @@ innobase_start_or_create_for_mysql(void)
n[i] = i; n[i] = i;
os_thread_create(io_handler_thread, n + i, thread_ids + i); thread_handles[i] = os_thread_create(io_handler_thread, n + i, thread_ids + i);
thread_started[i] = true;
} }
if (srv_n_log_files * srv_log_file_size * UNIV_PAGE_SIZE if (srv_n_log_files * srv_log_file_size * UNIV_PAGE_SIZE
...@@ -2722,19 +2739,22 @@ innobase_start_or_create_for_mysql(void) ...@@ -2722,19 +2739,22 @@ innobase_start_or_create_for_mysql(void)
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
/* Create the thread which watches the timeouts /* Create the thread which watches the timeouts
for lock waits */ for lock waits */
os_thread_create( thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create(
lock_wait_timeout_thread, lock_wait_timeout_thread,
NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS);
thread_started[2 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which warns of long semaphore waits */ /* Create the thread which warns of long semaphore waits */
os_thread_create( thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_error_monitor_thread, srv_error_monitor_thread,
NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS);
thread_started[3 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which prints InnoDB monitor info */ /* Create the thread which prints InnoDB monitor info */
os_thread_create( thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_monitor_thread, srv_monitor_thread,
NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
thread_started[4 + SRV_MAX_N_IO_THREADS] = true;
} }
/* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */ /* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */
...@@ -2761,26 +2781,30 @@ innobase_start_or_create_for_mysql(void) ...@@ -2761,26 +2781,30 @@ innobase_start_or_create_for_mysql(void)
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
os_thread_create( thread_handles[1 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_master_thread, srv_master_thread,
NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS)); NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
thread_started[1 + SRV_MAX_N_IO_THREADS] = true;
} }
if (!srv_read_only_mode if (!srv_read_only_mode
&& srv_force_recovery < SRV_FORCE_NO_BACKGROUND) { && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
os_thread_create( thread_handles[5 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_purge_coordinator_thread, srv_purge_coordinator_thread,
NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS); NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS);
thread_started[5 + SRV_MAX_N_IO_THREADS] = true;
ut_a(UT_ARR_SIZE(thread_ids) ut_a(UT_ARR_SIZE(thread_ids)
> 5 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS); > 5 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS);
/* We've already created the purge coordinator thread above. */ /* We've already created the purge coordinator thread above. */
for (i = 1; i < srv_n_purge_threads; ++i) { for (i = 1; i < srv_n_purge_threads; ++i) {
os_thread_create( thread_handles[5 + i + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_worker_thread, NULL, srv_worker_thread, NULL,
thread_ids + 5 + i + SRV_MAX_N_IO_THREADS); thread_ids + 5 + i + SRV_MAX_N_IO_THREADS);
thread_started[5 + i + SRV_MAX_N_IO_THREADS] = true;
} }
srv_start_wait_for_purge_to_start(); srv_start_wait_for_purge_to_start();
...@@ -2790,9 +2814,12 @@ innobase_start_or_create_for_mysql(void) ...@@ -2790,9 +2814,12 @@ innobase_start_or_create_for_mysql(void)
} }
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL); buf_flush_page_cleaner_thread_handle = os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL);
buf_flush_page_cleaner_thread_started = true;
} }
os_thread_create(buf_flush_lru_manager_thread, NULL, NULL);
buf_flush_lru_manager_thread_handle = os_thread_create(buf_flush_lru_manager_thread, NULL, NULL);
buf_flush_lru_manager_thread_started = true;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/* buf_debug_prints = TRUE; */ /* buf_debug_prints = TRUE; */
...@@ -2943,10 +2970,12 @@ innobase_start_or_create_for_mysql(void) ...@@ -2943,10 +2970,12 @@ innobase_start_or_create_for_mysql(void)
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
/* Create the buffer pool dump/load thread */ /* Create the buffer pool dump/load thread */
os_thread_create(buf_dump_thread, NULL, NULL); buf_dump_thread_handle = os_thread_create(buf_dump_thread, NULL, NULL);
buf_dump_thread_started = true;
/* Create the dict stats gathering thread */ /* Create the dict stats gathering thread */
os_thread_create(dict_stats_thread, NULL, NULL); dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL);
dict_stats_thread_started = true;
/* Create the thread that will optimize the FTS sub-system. */ /* Create the thread that will optimize the FTS sub-system. */
fts_optimize_init(); fts_optimize_init();
...@@ -3115,6 +3144,42 @@ innobase_shutdown_for_mysql(void) ...@@ -3115,6 +3144,42 @@ innobase_shutdown_for_mysql(void)
dict_stats_thread_deinit(); dict_stats_thread_deinit();
} }
#ifdef __WIN__
/* MDEV-361: ha_innodb.dll leaks handles on Windows
MDEV-7403: should not pass recv_writer_thread_handle to
CloseHandle().
On Windows we should call CloseHandle() for all
open thread handles. */
if (os_thread_count == 0) {
for (i = 0; i < SRV_MAX_N_IO_THREADS + 6 + 32; ++i) {
if (thread_started[i]) {
CloseHandle(thread_handles[i]);
}
}
if (buf_flush_page_cleaner_thread_started) {
CloseHandle(buf_flush_page_cleaner_thread_handle);
}
if (buf_dump_thread_started) {
CloseHandle(buf_dump_thread_handle);
}
if (dict_stats_thread_started) {
CloseHandle(dict_stats_thread_handle);
}
if (buf_flush_lru_manager_thread_started) {
CloseHandle(buf_flush_lru_manager_thread_handle);
}
if (srv_redo_log_follow_thread_started) {
CloseHandle(srv_redo_log_follow_thread_handle);
}
}
#endif /* __WIN __ */
/* This must be disabled before closing the buffer pool /* This must be disabled before closing the buffer pool
and closing the data dictionary. */ and closing the data dictionary. */
btr_search_disable(); btr_search_disable();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment