Skip to content

Commit 60c712a

Browse files
committed
Bug#22455198: THREAD HANDLE LEAK IN THE CONNECTION HANDLER
The problem was a thread handle resource leakage when creating threads for handling connections on Windows. This could lead to Windows servers eventually running out of handles. This was a regression introduced in 5.7 by WL#6407. In this WL we added support for joining threads on Windows in order to do proper thread cleanup during shutdown. In order to do this we had to keep the thread handle open as it is needed for joining the thread. The bug was that the handle was kept open also for threads that are detached. Such threads are never joined and thus the handle was not closed until the server terminated. The (by far) most common type of thread which is detached, is threads for handling connections. This patch fixes the problem by closing thread handles right after thread creation if the thread is created as a detached thread.
1 parent 47badc9 commit 60c712a

32 files changed

+103
-121
lines changed

client/mysqlimport.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -657,9 +657,7 @@ int main(int argc, char **argv)
657657
my_thread_handle mainthread; /* Thread descriptor */
658658
my_thread_attr_t attr; /* Thread attributes */
659659
my_thread_attr_init(&attr);
660-
#ifndef _WIN32
661-
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
662-
#endif
660+
my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_DETACHED);
663661

664662
native_mutex_init(&counter_mutex, NULL);
665663
native_cond_init(&count_threshold);

client/mysqlslap.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -1832,9 +1832,7 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
18321832
con.limit= limit;
18331833

18341834
my_thread_attr_init(&attr);
1835-
#ifndef _WIN32
1836-
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1837-
#endif
1835+
my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_DETACHED);
18381836

18391837
native_mutex_lock(&counter_mutex);
18401838
thread_counter= 0;

include/my_thread.h

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -54,7 +54,12 @@ C_MODE_START
5454
typedef volatile LONG my_thread_once_t;
5555
typedef DWORD my_thread_t;
5656
typedef struct thread_attr
57-
{ DWORD dwStackSize; } my_thread_attr_t;
57+
{
58+
DWORD dwStackSize;
59+
int detachstate;
60+
} my_thread_attr_t;
61+
#define MY_THREAD_CREATE_JOINABLE 0
62+
#define MY_THREAD_CREATE_DETACHED 1
5863
typedef void * (__cdecl *my_start_routine)(void *);
5964
#define MY_THREAD_ONCE_INIT 0
6065
#define MY_THREAD_ONCE_INPROGRESS 1
@@ -63,6 +68,8 @@ typedef void * (__cdecl *my_start_routine)(void *);
6368
typedef pthread_once_t my_thread_once_t;
6469
typedef pthread_t my_thread_t;
6570
typedef pthread_attr_t my_thread_attr_t;
71+
#define MY_THREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
72+
#define MY_THREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
6673
typedef void *(* my_start_routine)(void *);
6774
#define MY_THREAD_ONCE_INIT PTHREAD_ONCE_INIT
6875
#endif
@@ -99,6 +106,8 @@ static inline int my_thread_attr_init(my_thread_attr_t *attr)
99106
{
100107
#ifdef _WIN32
101108
attr->dwStackSize= 0;
109+
/* Set to joinable by default to match Linux */
110+
attr->detachstate= MY_THREAD_CREATE_JOINABLE;
102111
return 0;
103112
#else
104113
return pthread_attr_init(attr);
@@ -108,7 +117,9 @@ static inline int my_thread_attr_init(my_thread_attr_t *attr)
108117
static inline int my_thread_attr_destroy(my_thread_attr_t *attr)
109118
{
110119
#ifdef _WIN32
111-
memset(attr, 0, sizeof(*attr));
120+
attr->dwStackSize= 0;
121+
/* Set to joinable by default to match Linux */
122+
attr->detachstate= MY_THREAD_CREATE_JOINABLE;
112123
return 0;
113124
#else
114125
return pthread_attr_destroy(attr);
@@ -126,6 +137,17 @@ static inline int my_thread_attr_setstacksize(my_thread_attr_t *attr,
126137
#endif
127138
}
128139

140+
static inline int my_thread_attr_setdetachstate(my_thread_attr_t *attr,
141+
int detachstate)
142+
{
143+
#ifdef _WIN32
144+
attr->detachstate= detachstate;
145+
return 0;
146+
#else
147+
return pthread_attr_setdetachstate(attr, detachstate);
148+
#endif
149+
}
150+
129151
static inline int my_thread_attr_getstacksize(my_thread_attr_t *attr,
130152
size_t *stacksize)
131153
{

mysys/my_thread.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -104,8 +104,22 @@ int my_thread_create(my_thread_handle *thread, const my_thread_attr_t *attr,
104104

105105
thread->handle= (HANDLE)_beginthreadex(NULL, stack_size, win_thread_start,
106106
par, 0, &thread->thread);
107+
107108
if (thread->handle)
109+
{
110+
/* Note that JOINABLE is default, so attr == NULL => JOINABLE. */
111+
if (attr && attr->detachstate == MY_THREAD_CREATE_DETACHED)
112+
{
113+
/*
114+
Close handles for detached threads right away to avoid leaking
115+
handles. For joinable threads we need the handle during
116+
my_thread_join. It will be closed there.
117+
*/
118+
CloseHandle(thread->handle);
119+
thread->handle= NULL;
120+
}
108121
return 0;
122+
}
109123

110124
my_osmaperr(GetLastError());
111125
free(par);

mysys/thr_lock.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -1460,18 +1460,16 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
14601460
my_message_stderr(0, "Got error %d from pthread_attr_init",errno);
14611461
exit(1);
14621462
}
1463-
#ifndef _WIN32
1464-
if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
1463+
if ((error= my_thread_attr_setdetachstate(&thr_attr, MY_THREAD_CREATE_DETACHED)))
14651464
{
14661465
my_message_stderr(0, "Got error %d from "
1467-
"pthread_attr_setdetachstate", errno);
1466+
"my_thread_attr_setdetachstate", errno);
14681467
exit(1);
14691468
}
1470-
#endif
14711469
if ((error= my_thread_attr_setstacksize(&thr_attr,65536L)))
14721470
{
14731471
my_message_stderr(0, "Got error %d from "
1474-
"pthread_attr_setstacksize", error);
1472+
"my_thread_attr_setstacksize", error);
14751473
exit(1);
14761474
}
14771475
for (i=0 ; i < (int) array_elements(lock_counts) ; i++)

plugin/daemon_example/daemon_example.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -134,9 +134,7 @@ static int daemon_example_plugin_init(void *p)
134134
my_write(con->heartbeat_file, (uchar*) buffer, strlen(buffer), MYF(0));
135135

136136
my_thread_attr_init(&attr);
137-
#ifndef _WIN32
138-
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
139-
#endif
137+
my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
140138

141139

142140
/* now create the thread */

plugin/semisync/semisync_master_ack_receiver.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -75,8 +75,8 @@ bool Ack_receiver::start()
7575

7676
if (DBUG_EVALUATE_IF("rpl_semisync_simulate_create_thread_failure", 1, 0) ||
7777
my_thread_attr_init(&attr) != 0 ||
78+
my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE) != 0 ||
7879
#ifndef _WIN32
79-
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) != 0 ||
8080
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0 ||
8181
#endif
8282
mysql_thread_create(key_ss_thread_Ack_receiver_thread, &m_pid,

plugin/test_service_sql_api/test_session_detach.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -709,9 +709,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
709709
{
710710
my_thread_attr_t attr; /* Thread attributes */
711711
my_thread_attr_init(&attr);
712-
#ifndef _WIN32
713-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
714-
#endif
712+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
715713

716714
struct test_thread_context context;
717715

plugin/test_service_sql_api/test_session_in_thd.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -150,9 +150,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
150150
{
151151
my_thread_attr_t attr; /* Thread attributes */
152152
my_thread_attr_init(&attr);
153-
#ifndef _WIN32
154-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
155-
#endif
153+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
156154

157155
struct test_thread_context context;
158156

plugin/test_service_sql_api/test_session_info.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -1005,9 +1005,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
10051005
{
10061006
my_thread_attr_t attr; /* Thread attributes */
10071007
my_thread_attr_init(&attr);
1008-
#ifndef _WIN32
1009-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1010-
#endif
1008+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
10111009

10121010
struct test_thread_context context;
10131011

plugin/test_service_sql_api/test_sql_2_sessions.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -807,9 +807,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
807807
{
808808
my_thread_attr_t attr; /* Thread attributes */
809809
my_thread_attr_init(&attr);
810-
#ifndef _WIN32
811-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
812-
#endif
810+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
813811

814812
struct test_thread_context context;
815813

plugin/test_service_sql_api/test_sql_all_col_types.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -965,9 +965,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
965965
{
966966
my_thread_attr_t attr; /* Thread attributes */
967967
my_thread_attr_init(&attr);
968-
#ifndef _WIN32
969-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
970-
#endif
968+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
971969

972970
struct test_thread_context context;
973971

plugin/test_service_sql_api/test_sql_cmds_1.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -653,9 +653,7 @@ static int test_query_kill(void *p)
653653
my_thread_attr_t attr;
654654

655655
my_thread_attr_init(&attr);
656-
#ifndef _WIN32
657-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
658-
#endif
656+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
659657

660658
if (my_thread_create(&thread_handle, &attr, (void *(*)(void *))test_session_thread, &tdata) != 0)
661659
{

plugin/test_service_sql_api/test_sql_commit.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -850,9 +850,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
850850
{
851851
my_thread_attr_t attr; /* Thread attributes */
852852
my_thread_attr_init(&attr);
853-
#ifndef _WIN32
854-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
855-
#endif
853+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
856854

857855
struct test_thread_context context;
858856

plugin/test_service_sql_api/test_sql_complex.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -937,9 +937,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
937937
{
938938
my_thread_attr_t attr; /* Thread attributes */
939939
my_thread_attr_init(&attr);
940-
#ifndef _WIN32
941-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
942-
#endif
940+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
943941

944942
struct test_thread_context context;
945943

plugin/test_service_sql_api/test_sql_errors.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -857,9 +857,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
857857
{
858858
my_thread_attr_t attr; /* Thread attributes */
859859
my_thread_attr_init(&attr);
860-
#ifndef _WIN32
861-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
862-
#endif
860+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
863861

864862
struct test_thread_context context;
865863

plugin/test_service_sql_api/test_sql_lock.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -923,9 +923,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
923923
{
924924
my_thread_attr_t attr; /* Thread attributes */
925925
my_thread_attr_init(&attr);
926-
#ifndef _WIN32
927-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
928-
#endif
926+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
929927

930928
struct test_thread_context context;
931929

plugin/test_service_sql_api/test_sql_processlist.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -750,9 +750,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
750750
{
751751
my_thread_attr_t attr; /* Thread attributes */
752752
my_thread_attr_init(&attr);
753-
#ifndef _WIN32
754-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
755-
#endif
753+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
756754

757755
struct test_thread_context context;
758756

plugin/test_service_sql_api/test_sql_replication.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -854,9 +854,7 @@ static void test_in_spawned_thread(void *p, void (*test_function)(void *))
854854
{
855855
my_thread_attr_t attr; /* Thread attributes */
856856
my_thread_attr_init(&attr);
857-
#ifndef _WIN32
858-
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
859-
#endif
857+
(void) my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
860858

861859
struct test_thread_context context;
862860

0 commit comments

Comments
 (0)