Tarantool development patches archive
 help / color / mirror / Atom feed
From: Serge Petrenko <sergepetrenko@tarantool.org>
To: alexander.turenko@tarantool.org
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH v2 1/2] build: link bundled libcurl with c-ares
Date: Tue, 21 Jan 2020 14:54:31 +0300	[thread overview]
Message-ID: <853c32f414c954d38b2621afc7babd57a6e031c4.1579605136.git.sergepetrenko@tarantool.org> (raw)
In-Reply-To: <cover.1579605136.git.sergepetrenko@tarantool.org>

libcurl has a built-in threaded resolver used for asynchronous DNS
requests, however, when DNS server is slow to respond, the request still
hangs tarantool until it is finished. The reason is that curl calls
thread_join on the resolving thread internally upon timeout, making the
calling thread hang until resolution has ended.
Use c-ares as an asynchronous resolver instead to eliminate the problem.

Closes #4591
---
 .gitmodules              |  3 ++
 CMakeLists.txt           |  6 ++++
 cmake/BuildAres.cmake    | 61 ++++++++++++++++++++++++++++++++++++++++
 cmake/BuildLibCURL.cmake | 31 ++++++++++++++++++--
 src/CMakeLists.txt       |  3 +-
 third_party/c-ares       |  1 +
 6 files changed, 102 insertions(+), 3 deletions(-)
 create mode 100644 cmake/BuildAres.cmake
 create mode 160000 third_party/c-ares

diff --git a/.gitmodules b/.gitmodules
index 76303e0c5..d45e9ce8b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -40,3 +40,6 @@
 [submodule "third_party/curl"]
 	path = third_party/curl
 	url = https://github.com/tarantool/curl.git
+[submodule "third_party/c-ares"]
+	path = third_party/c-ares
+	url = https://github.com/tarantool/c-ares.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca968eb8d..1d80b6806 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -345,7 +345,13 @@ endif()
 # Curl
 #
 option(ENABLE_BUNDLED_LIBCURL "Enable building of the bundled libcurl" ON)
+option(BUNDLED_LIBCURL_USE_ARES "Build curl with bundled c-ares"
+       ${ENABLE_BUNDLED_LIBCURL})
 if (ENABLE_BUNDLED_LIBCURL)
+    if(BUNDLED_LIBCURL_USE_ARES)
+        include(BuildAres)
+        ares_build()
+    endif()
     include(BuildLibCURL)
     curl_build()
     add_dependencies(build_bundled_libs bundled-libcurl)
diff --git a/cmake/BuildAres.cmake b/cmake/BuildAres.cmake
new file mode 100644
index 000000000..0f9f174ce
--- /dev/null
+++ b/cmake/BuildAres.cmake
@@ -0,0 +1,61 @@
+# A macro to build the bundled libcares
+macro(ares_build)
+    set(ARES_SOURCE_DIR ${PROJECT_SOURCE_DIR}/third_party/c-ares)
+    set(ARES_BINARY_DIR ${PROJECT_BINARY_DIR}/build/ares/work)
+    set(ARES_INSTALL_DIR ${PROJECT_BINARY_DIR}/build/ares/dest)
+
+    # See BuildLibCURL.cmake for details.
+    set(ARES_CFLAGS "")
+    if (TARGET_OS_DARWIN AND NOT "${CMAKE_OSX_SYSROOT}" STREQUAL "")
+        set(ARES_CFLAGS "${ARES_CFLAGS} ${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT}")
+    endif()
+
+    set(ARES_CMAKE_FLAGS "-DCARES_STATIC=ON")
+    list(APPEND ARES_CMAKE_FLAGS "-DCARES_SHARED=OFF")
+    list(APPEND ARES_CMAKE_FLAGS "-DCARES_BUILD_TOOLS=OFF")
+    # We buid both static and shared versions of curl, so ares
+    # has to be built with -fPIC for the shared version.
+    list(APPEND ARES_CMAKE_FLAGS "-DCARES_STATIC_PIC=ON")
+    # Even though we set the external project's install dir
+    # below, we still need to pass the corresponding install
+    # prefix via cmake arguments.
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_INSTALL_PREFIX=${ARES_INSTALL_DIR}")
+    # The default values for the options below are not always
+    # "./lib", "./bin"  and "./include", while curl expects them
+    # to be.
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_INSTALL_LIBDIR=lib")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_INSTALL_INCLUDEDIR=include")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_INSTALL_BINDIR=bin")
+
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_LINKER=${CMAKE_LINKER}")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_AR=${CMAKE_AR}")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_RANLIB=${CMAKE_RANLIB}")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_NM=${CMAKE_NM}")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_STRIP=${CMAKE_STRIP}")
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_C_FLAGS=${ARES_CFLAGS}")
+    # In hardened mode, which enables -fPIE by default,
+    # the cmake checks don't work without -fPIC.
+    list(APPEND ARES_CMAKE_FLAGS "-DCMAKE_REQUIRED_FLAGS=-fPIC")
+
+    include(ExternalProject)
+    ExternalProject_Add(
+        bundled-ares-project
+        SOURCE_DIR ${ARES_SOURCE_DIR}
+        INSTALL_DIR ${ARES_INSTALL_DIR}
+        DOWNLOAD_DIR ${ARES_BINARY_DIR}
+        TMP_DIR ${ARES_BINARY_DIR}/tmp
+        STAMP_DIR ${ARES_BINARY_DIR}/stamp
+        BINARY_DIR ${ARES_BINARY_DIR}
+        CMAKE_ARGS ${ARES_CMAKE_FLAGS})
+
+    add_library(bundled-ares STATIC IMPORTED GLOBAL)
+    set_target_properties(bundled-ares PROPERTIES IMPORTED_LOCATION
+        ${ARES_INSTALL_DIR}/lib/libcares.a)
+    add_dependencies(bundled-ares bundled-ares-project)
+
+    unset(ARES_CMAKE_FLAGS)
+    unset(ARES_CFLAGS)
+    unset(ARES_BINARY_DIR)
+    unset(ARES_SOURCE_DIR)
+endmacro(ares_build)
diff --git a/cmake/BuildLibCURL.cmake b/cmake/BuildLibCURL.cmake
index 6d40ab045..756297878 100644
--- a/cmake/BuildLibCURL.cmake
+++ b/cmake/BuildLibCURL.cmake
@@ -19,6 +19,21 @@ macro(curl_build)
     get_filename_component(FOUND_OPENSSL_ROOT_DIR ${OPENSSL_INCLUDE_DIR} DIRECTORY)
     set(LIBCURL_OPENSSL_OPT "--with-ssl=${FOUND_OPENSSL_ROOT_DIR}")
 
+    # Use either c-ares bundled with tarantool or
+    # libcurl-default threaded resolver.
+    if(BUNDLED_LIBCURL_USE_ARES)
+        set(ASYN_DNS_USED "ares")
+        set(ASYN_DNS_UNUSED "threaded-resolver")
+        set(ASYN_DNS_PATH "=${ARES_INSTALL_DIR}")
+    else()
+        set(ASYN_DNS_USED "threaded-resolver")
+        set(ASYN_DNS_UNUSED "ares")
+        set(ASYN_DNS_PATH "")
+    endif()
+
+    set(ENABLED_DNS_OPT "--enable-${ASYN_DNS_USED}${ASYN_DNS_PATH}")
+    set(DISABLED_DNS_OPT "--disable-${ASYN_DSN_UNUSED}")
+
     # Pass -isysroot=<SDK_PATH> option on Mac OS to a preprocessor
     # and a C compiler to find header files installed with an SDK.
     #
@@ -100,17 +115,17 @@ macro(curl_build)
                 --without-zsh-functions-dir
                 --without-fish-functions-dir
 
+                ${ENABLED_DNS_OPT}
                 --enable-http
                 --enable-proxy
                 --enable-ipv6
-                --enable-threaded-resolver
                 --enable-unix-sockets
                 --enable-cookies
                 --enable-http-auth
                 --enable-mime
                 --enable-dateparse
 
-                --disable-ares
+                ${DISABLED_DNS_OPT}
                 --disable-ftp
                 --disable-file
                 --disable-ldap
@@ -140,14 +155,26 @@ macro(curl_build)
     add_library(bundled-libcurl STATIC IMPORTED GLOBAL)
     set_target_properties(bundled-libcurl PROPERTIES IMPORTED_LOCATION
         ${LIBCURL_INSTALL_DIR}/lib/libcurl.a)
+    if (BUNDLED_LIBCURL_USE_ARES)
+        # Need to build ares first
+        add_dependencies(bundled-libcurl-project bundled-ares)
+    endif()
     add_dependencies(bundled-libcurl bundled-libcurl-project)
 
     set(CURL_INCLUDE_DIRS ${LIBCURL_INSTALL_DIR}/include)
     set(CURL_LIBRARIES bundled-libcurl ${LIBZ_LIBRARY})
+    if (BUNDLED_LIBCURL_USE_ARES)
+        set(CURL_LIBRARIES ${CURL_LIBRARIES} bundled-ares)
+    endif()
     if (TARGET_OS_LINUX OR TARGET_OS_FREEBSD)
         set(CURL_LIBRARIES ${CURL_LIBRARIES} rt)
     endif()
 
+    unset(ASYN_DNS_USED)
+    unset(ASYN_DNS_UNUSED)
+    unset(ASYN_DNS_PATH)
+    unset(ENABLED_DNS_OPT)
+    unset(DISABLED_DNS_OPT)
     unset(LIBCURL_CPPFLAGS)
     unset(LIBCURL_CFLAGS)
     unset(FOUND_OPENSSL_ROOT_DIR)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e12de6005..bdeec5f89 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -227,7 +227,8 @@ if(BUILD_STATIC)
             list(APPEND EXPORT_LIST ${SYMBOLS_LIB})
             # set variable to allow rescan (CMake depended)
             set(SYMBOLS_LIB "SYMBOLS_LIB-NOTFOUND")
-        elseif (${libstatic} STREQUAL bundled-libcurl)
+        elseif (${libstatic} STREQUAL bundled-libcurl OR
+                ${libstatic} STREQUAL bundled-ares)
             message("We don't need to export symbols from statically linked libcurl, skipped")
         else()
             message(WARNING "${libstatic} should be a static")
diff --git a/third_party/c-ares b/third_party/c-ares
new file mode 160000
index 000000000..56a74c501
--- /dev/null
+++ b/third_party/c-ares
@@ -0,0 +1 @@
+Subproject commit 56a74c501a615c16ca54d608d1796e966f9a503a
-- 
2.21.0 (Apple Git-122)

  reply	other threads:[~2020-01-21 11:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-21 11:54 [Tarantool-patches] [PATCH v2 0/2] build: link curl " Serge Petrenko
2020-01-21 11:54 ` Serge Petrenko [this message]
2020-02-08 19:42   ` [Tarantool-patches] [PATCH v2 1/2] build: link bundled libcurl " Alexander Turenko
2020-03-03 16:46     ` Serge Petrenko
2020-03-03 16:51       ` Serge Petrenko
2020-03-03 23:20       ` Alexander Turenko
2020-03-04 12:42       ` Alexander Turenko
2020-03-05  5:27   ` Kirill Yukhin
2020-01-21 11:54 ` [Tarantool-patches] [PATCH v2 2/2] build: add bundled curl and c-ares to version output Serge Petrenko
2020-03-04 12:03   ` Alexander Turenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=853c32f414c954d38b2621afc7babd57a6e031c4.1579605136.git.sergepetrenko@tarantool.org \
    --to=sergepetrenko@tarantool.org \
    --cc=alexander.turenko@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v2 1/2] build: link bundled libcurl with c-ares' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox