Fixed crash by libcurl with open ssl in multi-threading 41/165741/11
authortaeyoon0.lee <taeyoon0.lee@samsung.com>
Wed, 3 Jan 2018 07:24:00 +0000 (16:24 +0900)
committertaeyoon0.lee <taeyoon0.lee@samsung.com>
Wed, 10 Jan 2018 14:13:25 +0000 (23:13 +0900)
https://curl.haxx.se/libcurl/c/threadsafe.html

Change-Id: I5bd0620a2240506445a7f07d345111952d28f8fd

build/tizen/adaptor/Makefile.am
build/tizen/adaptor/configure.ac
packaging/dali-adaptor.spec
platform-abstractions/tizen/resource-loader/network/file-download.cpp
platform-abstractions/tizen/resource-loader/network/file-download.h

index 4043ee9..54057ce 100644 (file)
@@ -381,6 +381,7 @@ LIBDALI_ADAPTOR_LA_CXXFLAGS = \
                       $(LIBDRM_CFLAGS) \
                       $(LIBEXIF_CFLAGS) \
                       $(LIBCURL_CFLAGS) \
+                      $(LIBCRYPTO_CFLAGS) \
                       $(TPKP_CURL_CFLAGS) \
                       $(UTILX_CFLAGS)
 
@@ -408,6 +409,7 @@ LIBDALI_ADAPTOR_LA_LIBADD = \
                       $(LIBDRM_LIBS) \
                       $(LIBEXIF_LIBS) \
                       $(LIBCURL_LIBS) \
+                      $(LIBCRYPTO_LIBS) \
                       $(HARFBUZZ_LIBS) \
                       $(TPKP_CURL_LIBS) \
                       $(UTILX_LIBS) \
index 4a7f614..14c137a 100644 (file)
@@ -43,6 +43,7 @@ PKG_CHECK_MODULES(PNG, libpng)
 PKG_CHECK_MODULES(LIBEXIF, libexif)
 PKG_CHECK_MODULES(LIBDRM, libdrm)
 PKG_CHECK_MODULES(LIBCURL, libcurl)
+PKG_CHECK_MODULES(LIBCRYPTO, libcrypto)
 PKG_CHECK_MODULES(HARFBUZZ, harfbuzz)
 PKG_CHECK_MODULES(FRIBIDI, fribidi)
 PKG_CHECK_MODULES(EVAS, evas)
index 089ccbe..9582d9b 100644 (file)
@@ -85,6 +85,8 @@ BuildRequires:  fribidi-devel
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(capi-system-sensor)
 
+BuildRequires:  pkgconfig(libcrypto)
+
 %if %{with wayland}
 
 ####### BUILDING FOR WAYLAND #######
index 80f67fa..1908597 100755 (executable)
@@ -20,7 +20,9 @@
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <pthread.h>
 #include <curl/curl.h>
+#include <openssl/crypto.h>
 #include <cstring>
 
 // INTERNAL INCLUDES
@@ -55,7 +57,6 @@ const long EXCLUDE_BODY = 1L;
  */
 static Dali::TizenPlatform::Network::CurlEnvironment gCurlEnvironment;
 
-
 void ConfigureCurlOptions( CURL* curlHandle, const std::string& url )
 {
   curl_easy_setopt( curlHandle, CURLOPT_URL, url.c_str() );
@@ -212,18 +213,74 @@ bool DownloadFile( CURL* curlHandle,
 namespace Network
 {
 
+std::mutex* CurlEnvironment::mMutexs = NULL;
+
 CurlEnvironment::CurlEnvironment()
 {
   // Must be called before we attempt any loads. e.g. by using curl_easy_init()
   // and before we start any threads.
   curl_global_init(CURL_GLOBAL_ALL);
+
+ // libcurl with openssl needs locking_function and thread id for threadsafe
+ // https://curl.haxx.se/libcurl/c/threadsafe.html
+ // https://www.openssl.org/docs/man1.0.2/crypto/threads.html#DESCRIPTION
+ // SetLockingFunction sets locking_function and get thread id by the guide.
+  SetLockingFunction();
 }
 
 CurlEnvironment::~CurlEnvironment()
 {
+  UnsetLockingFunction();
+
   curl_global_cleanup();
 }
 
+// libcurl with openssl needs locking_function and thread id for threadsafe
+// https://curl.haxx.se/libcurl/c/threadsafe.html
+// https://www.openssl.org/docs/man1.0.2/crypto/threads.html#DESCRIPTION
+void CurlEnvironment::OnOpenSSLLocking( int mode, int n, const char* file, int line )
+{
+  if( mode & CRYPTO_LOCK )
+  {
+    mMutexs[n].lock();
+  }
+  else
+  {
+    mMutexs[n].unlock();
+  }
+}
+
+unsigned long CurlEnvironment::GetThreadId()
+{
+  // If dali uses c++ thread, we may replace pthread_self() to this_thread::get_id()
+  return static_cast< unsigned long >( pthread_self() );
+}
+
+void CurlEnvironment::SetLockingFunction()
+{
+  if( mMutexs != NULL )
+  {
+    return;
+  }
+
+  mMutexs = new std::mutex[ CRYPTO_num_locks() ];
+
+  CRYPTO_set_id_callback( &CurlEnvironment::GetThreadId );
+  CRYPTO_set_locking_callback( &CurlEnvironment::OnOpenSSLLocking );
+}
+
+void CurlEnvironment::UnsetLockingFunction()
+{
+  if( mMutexs == NULL )
+  {
+    return;
+  }
+
+  CRYPTO_set_id_callback( NULL );
+  CRYPTO_set_locking_callback( NULL );
+  delete [] mMutexs;
+  mMutexs = NULL;
+}
 
 bool DownloadRemoteFileIntoMemory( const std::string& url,
                                    Dali::Vector<uint8_t>& dataBuffer,
index ee3d0f5..20380a0 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
 #include <string>
+#include <mutex> //c++11
 #include <stdint.h> // uint8
 
 namespace Dali
@@ -50,6 +51,24 @@ public:
    * Destructor calls curl_global_cleanup()
    */
   ~CurlEnvironment();
+
+  /**
+   * Locking function for libcurl with openssl
+   */
+  static void OnOpenSSLLocking( int mode, int n, const char* file, int line );
+
+  /**
+   * Gets thread id for libcurl with openssl
+   */
+  static unsigned long GetThreadId();
+
+private:
+
+  void SetLockingFunction();
+
+  void UnsetLockingFunction();
+
+  static std::mutex* mMutexs;
 };