4503 Vamsikrishna Bhagi 2012-10-30
(no message)
4502 Vamsikrishna Bhagi 2012-10-30
Bug#14547920 I_MAIN.BUG13115401 CAUSING VALGRIND REPORT
FAILURE ON PB2
Issue: The test i_main.bug13115401 which was added to fix
the bug #13115401 has introduced a sporadic valgrind
failure report on pushbuild specific to yaSSL build.
It being a sporadic issue, it can be reproduced once
or twice when the command below is run for around
50 times.
perl mysql-test-run.pl --timer --debug-server
--force --comment=n_mix-debug --vardir=var-n_mix
--mysqld=--binlog-format=mixed
--experimental=collections/default.experimental
--skip-ndb
--skip-test-list=collections/disabled-per-push.list
--unit-tests --valgrind
--valgrind-option=--gen-suppressions=all
--valgrind-option=--show-reachable=yes
Solution: The problem arises on a multi-threaded scenario
when a thread tries to create a session object
from GetSessions() method as another thread is
already doing a creation. As the memory allocated
in first thread is overridden by memory allocated
by the second thread, the memory allocated by the
first thread will be a leak in this case. This is
because the yassl session instance is not thread
safe. To make this instance creation process
compatible with multi-threading, a new instance
is created by with the help of yassl_pthread_once,
which will essentially check if the function used
for creating an instance is already called
previously or not.
@ extra/yassl/src/yassl_int.cpp
Bug#14547920 I_MAIN.BUG13115401 CAUSING VALGRIND REPORT
FAILURE ON PB2
The return value of the method GetSession() is a pointer
*sessionsInstance which is created after checking if the
pointer is empty or not. But this results in a leak when a
thread execution clears the check condition
if (!sessionsInstance) as the allocation for another thread
is going on at sessionsInstance = NEW_YS Sessions. To make
this process thread safe, yassl_pthread_once method is used
to create an instance which will see to that session is
created only once in existing context. It is implemented in
such a way that it checks the type of operating system, and
uses pthread_once for unix or uses a code snippet which does
the same task of pthread_once on windows in case it is
windows(kindly refer C++ documentation for more details on
pthread_once). Since pthread_once takes only void returning
functions as an argument, a new function Session_initialize
is implemented to create a session. The check variable
session_created is refreshed after deleting the
sessionInstance in yaSSL cleanup. Since a session is being
created only after the old one is cleared, there will not be
a memory leak.
added:
unittest/gunit/yassl/
unittest/gunit/yassl/CMakeLists.txt
unittest/gunit/yassl/yassl-t.cc
modified:
extra/yassl/include/yassl_int.hpp
extra/yassl/src/yassl_int.cpp
unittest/gunit/CMakeLists.txt
4501 Shivji Kumar Jha 2012-10-30 [merge]
BUG#14659685 - MAIN.MYSQLBINLOG_ROW_MYISAM.TEST MAIN.MYSQLBINLOG_ROW_INNODB.TEST
ARE SKIPPED
merge from 5.5 into 5.6
renamed:
mysql-test/include/mysqlbinlog_row_engine.inc => mysql-test/extra/binlog_tests/mysqlbinlog_row_engine.inc
mysql-test/r/mysqlbinlog-cp932.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog-cp932.result
mysql-test/r/mysqlbinlog_base64.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog_base64.result
mysql-test/r/mysqlbinlog_row.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result
mysql-test/r/mysqlbinlog_row_innodb.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result
mysql-test/r/mysqlbinlog_row_myisam.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result
mysql-test/r/mysqlbinlog_row_trans.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_trans.result
mysql-test/r/mysqlbinlog_start_stop.result => mysql-test/suite/binlog/r/binlog_mysqlbinlog_start_stop.result
mysql-test/t/mysqlbinlog-cp932-master.opt => mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932-master.opt
mysql-test/t/mysqlbinlog-cp932.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog-cp932.test
mysql-test/t/mysqlbinlog_base64.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog_base64.test
mysql-test/t/mysqlbinlog_row.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test
mysql-test/t/mysqlbinlog_row_innodb.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test
mysql-test/t/mysqlbinlog_row_myisam.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test
mysql-test/t/mysqlbinlog_row_trans.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_trans.test
mysql-test/t/mysqlbinlog_start_stop.test => mysql-test/suite/binlog/t/binlog_mysqlbinlog_start_stop.test
modified:
mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_innodb.test
mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_myisam.test
=== modified file 'extra/yassl/include/yassl_int.hpp'
--- a/extra/yassl/include/yassl_int.hpp 2012-07-24 13:24:00 +0000
+++ b/extra/yassl/include/yassl_int.hpp 2012-10-30 06:14:23 +0000
@@ -278,6 +278,7 @@ public:
~Sessions();
+ friend void Session_initialize();
friend Sessions& GetSessions(); // singleton creator
private:
Sessions(const Sessions&); // hide copy
=== modified file 'extra/yassl/src/yassl_int.cpp'
--- a/extra/yassl/src/yassl_int.cpp 2012-07-24 13:24:00 +0000
+++ b/extra/yassl/src/yassl_int.cpp 2012-10-30 06:14:23 +0000
@@ -26,7 +26,9 @@
#include "pthread.h"
#endif
-
+#ifdef __WIN__
+ #include<Windows.h>
+#endif
#ifdef HAVE_LIBZ
#include "zlib.h"
#endif
@@ -719,6 +721,58 @@ void SSL::set_pending(Cipher suite)
}
}
+#ifdef __WIN__
+typedef volatile LONG yassl_pthread_once_t;
+#define YASSL_PTHREAD_ONCE_INIT 0
+#define YASSL_PTHREAD_ONCE_INPROGRESS 1
+#define YASSL_PTHREAD_ONCE_DONE 2
+
+int yassl_pthread_once(yassl_pthread_once_t *once_control,
+ void (*init_routine)(void))
+{
+ LONG state;
+
+ /*
+ Do "dirty" read to find out if initialization is already done, to
+ save an interlocked operation in common case. Memory barriers are ensured by
+ Visual C++ volatile implementation.
+ */
+ if (*once_control == YASSL_PTHREAD_ONCE_DONE)
+ return 0;
+
+ state= InterlockedCompareExchange(once_control, YASSL_PTHREAD_ONCE_INPROGRESS,
+ YASSL_PTHREAD_ONCE_INIT);
+
+ switch(state)
+ {
+ case YASSL_PTHREAD_ONCE_INIT:
+ /* This is initializer thread */
+ (*init_routine)();
+ *once_control= YASSL_PTHREAD_ONCE_DONE;
+ break;
+
+ case YASSL_PTHREAD_ONCE_INPROGRESS:
+ /* init_routine in progress. Wait for its completion */
+ while(*once_control == YASSL_PTHREAD_ONCE_INPROGRESS)
+ {
+ Sleep(1);
+ }
+ break;
+ case YASSL_PTHREAD_ONCE_DONE:
+ /* Nothing to do */
+ break;
+ }
+ return 0;
+}
+#else
+#define yassl_pthread_once_t pthread_once_t
+#if defined(PTHREAD_ONCE_INITIALIZER)
+#define YASSL_PTHREAD_ONCE_INIT PTHREAD_ONCE_INITIALIZER
+#else
+#define YASSL_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
+#endif
+#define yassl_pthread_once(C,F) pthread_once(C,F)
+#endif // __WIN__
// store peer's random
void SSL::set_random(const opaque* random, ConnectionEnd sender)
@@ -1566,11 +1620,17 @@ SSL_SESSION::~SSL_SESSION()
static Sessions* sessionsInstance = 0;
+static yassl_pthread_once_t session_created= YASSL_PTHREAD_ONCE_INIT;
+
+void Session_initialize()
+{
+ sessionsInstance = NEW_YS Sessions;
+}
+
Sessions& GetSessions()
{
- if (!sessionsInstance)
- sessionsInstance = NEW_YS Sessions;
+ yassl_pthread_once(&session_created, Session_initialize);
return *sessionsInstance;
}
@@ -2629,6 +2689,7 @@ extern "C" void yaSSL_CleanUp()
yaSSL::ysDelete(yaSSL::sslFactoryInstance);
yaSSL::ysDelete(yaSSL::sessionsInstance);
yaSSL::ysDelete(yaSSL::errorsInstance);
+ yaSSL::session_created= YASSL_PTHREAD_ONCE_INIT;
// In case user calls more than once, prevent seg fault
yaSSL::sslFactoryInstance = 0;
=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt 2012-09-07 14:07:26 +0000
+++ b/unittest/gunit/CMakeLists.txt 2012-10-30 06:14:23 +0000
@@ -185,6 +185,9 @@ IF(GTEST_DOWNLOADED)
SET(GTEST_INCLUDE_DIR "${GTEST_SOURCE_DIR}/include" CACHE INTERNAL "")
ENDIF()
+IF (WITH_SSL STREQUAL "bundled")
+ ADD_SUBDIRECTORY(yassl)
+ENDIF()
INCLUDE_DIRECTORIES(
${GTEST_INCLUDE_DIRS}
=== added directory 'unittest/gunit/yassl'
=== added file 'unittest/gunit/yassl/CMakeLists.txt'
--- a/unittest/gunit/yassl/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/yassl/CMakeLists.txt 2012-10-30 06:14:23 +0000
@@ -0,0 +1,31 @@
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+INCLUDE_DIRECTORIES(
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_SOURCE_DIR}/unittest/gunit
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include
+ ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/include
+ ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL
+)
+
+ADD_DEFINITIONS(${SSL_DEFINES})
+
+## Do not treat warnings as error for yassl code
+STRING(REPLACE "-Werror" "" nowerr_flags "${CMAKE_CXX_FLAGS}")
+SET(CMAKE_CXX_FLAGS ${nowerr_flags})
+
+ADD_EXECUTABLE(yassl-t yassl-t.cc)
+TARGET_LINK_LIBRARIES(yassl-t gunit_small sqlgunitlib strings dbug regex)
=== added file 'unittest/gunit/yassl/yassl-t.cc'
--- a/unittest/gunit/yassl/yassl-t.cc 1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/yassl/yassl-t.cc 2012-10-30 06:14:23 +0000
@@ -0,0 +1,106 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
+
+// First include (the generated) my_config.h, to get correct platform defines.
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+
+#include "thread_utils.h"
+
+namespace {
+
+using thread::Notification;
+using thread::Thread;
+
+class Yassl_thread : public Thread
+{
+public:
+ Yassl_thread(Notification *go, Notification *done)
+ : m_sessions_instance(NULL), m_go(go), m_done(done)
+ {}
+ virtual void run()
+ {
+ // Wait until my creator tells me to go.
+ m_go->wait_for_notification();
+ yaSSL::Sessions &sessions= yaSSL::GetSessions();
+ m_sessions_instance= &sessions;
+ // Tell my creator I'm done.
+ m_done->notify();
+ }
+ yaSSL::Sessions *m_sessions_instance;
+private:
+ Notification *m_go;
+ Notification *m_done;
+};
+
+
+/**
+ Verify that yaSSL::sessionsInstance is indeed a singleton.
+ If any of the EXPECT_EQ below reports an error, it is not.
+ We can also run 'valgrind ./yassl-t'. If there are errors,
+ valgrind will report a multiple of
+ sizeof(yaSSL::Sessions) == 80
+ bytes lost.
+ */
+TEST(YasslTest, ManySessions)
+{
+ Notification go[5];
+ Notification done[5];
+ Yassl_thread t0(&go[0], &done[0]);
+ Yassl_thread t1(&go[1], &done[1]);
+ Yassl_thread t2(&go[2], &done[2]);
+ Yassl_thread t3(&go[3], &done[3]);
+ Yassl_thread t4(&go[4], &done[4]);
+
+ t0.start();
+ t1.start();
+ t2.start();
+ t3.start();
+ t4.start();
+
+ for (int ix= 0; ix < 5; ++ix)
+ go[ix].notify();
+
+ for (int ix= 0; ix < 5; ++ix)
+ done[ix].wait_for_notification();
+
+ // These are most likely to fail unless we use pthread_once.
+ EXPECT_EQ(t0.m_sessions_instance, t1.m_sessions_instance);
+ EXPECT_EQ(t0.m_sessions_instance, t2.m_sessions_instance);
+ EXPECT_EQ(t0.m_sessions_instance, t3.m_sessions_instance);
+ EXPECT_EQ(t0.m_sessions_instance, t4.m_sessions_instance);
+
+ // These rarely fail. If they do, we have more than two instances.
+ EXPECT_EQ(t1.m_sessions_instance, t2.m_sessions_instance);
+ EXPECT_EQ(t1.m_sessions_instance, t3.m_sessions_instance);
+ EXPECT_EQ(t1.m_sessions_instance, t4.m_sessions_instance);
+
+ EXPECT_EQ(t2.m_sessions_instance, t3.m_sessions_instance);
+ EXPECT_EQ(t2.m_sessions_instance, t4.m_sessions_instance);
+
+ EXPECT_EQ(t3.m_sessions_instance, t4.m_sessions_instance);
+
+ t0.join();
+ t1.join();
+ t2.join();
+ t3.join();
+ t4.join();
+ yaSSL_CleanUp();
+}
+
+}
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.6 branch (vamsikrishna.bhagi:4501 to 4503) | Vamsikrishna Bhagi | 16 Nov |