Ver código fonte

FindThreads: Use complete program to test for pthreads in libc

Our check for just `pthread_create` is not sufficient because there are
cases where that symbol may be found in libc but not all of pthreads.
We first tried to address this in commit e9a1ddc594 (FindThreads:
Replace the pthread symbol checking in libc., 2018-11-18,
v3.14.0-rc1~292^2) by switching to `pthread_kill`, but that had to be
reverted by commit 18320230ec (FindThreads: Revert libc symbol check to
pthread_create, 2019-02-27, v3.14.0-rc3~6^2) because there are other
cases where `pthread_kill` is in libc but the rest of pthreads is not.
Update our check to try a complete program using pthreads as an actual
application might.

Fixes: #18994
JerryShih 6 anos atrás
pai
commit
d53317130e
1 arquivos alterados com 35 adições e 6 exclusões
  1. 35 6
      Modules/FindThreads.cmake

+ 35 - 6
Modules/FindThreads.cmake

@@ -38,19 +38,42 @@ This module is not needed for C++11 and later if threading is done using
 #]=======================================================================]
 
 include (CheckLibraryExists)
-include (CheckSymbolExists)
 set(Threads_FOUND FALSE)
 set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
 set(CMAKE_REQUIRED_QUIET ${Threads_FIND_QUIETLY})
 
 if(CMAKE_C_COMPILER_LOADED)
   include (CheckIncludeFile)
+  include (CheckCSourceCompiles)
 elseif(CMAKE_CXX_COMPILER_LOADED)
   include (CheckIncludeFileCXX)
+  include (CheckCXXSourceCompiles)
 else()
   message(FATAL_ERROR "FindThreads only works if either C or CXX language is enabled")
 endif()
 
+# simple pthread test code
+set(PTHREAD_C_CXX_TEST_SOURCE [====[
+#include <pthread.h>
+
+void* test_func(void* data)
+{
+  return data;
+}
+
+int main(void)
+{
+  pthread_t thread;
+  pthread_create(&thread, NULL, test_func, NULL);
+  pthread_detach(thread);
+  pthread_join(thread, NULL);
+  pthread_atfork(NULL, NULL, NULL);
+  pthread_exit(NULL);
+
+  return 0;
+}
+]====])
+
 # Internal helper macro.
 # Do NOT even think about using it outside of this file!
 macro(_check_threads_lib LIBNAME FUNCNAME VARNAME)
@@ -109,8 +132,8 @@ if(CMAKE_C_COMPILER_LOADED)
 else()
   CHECK_INCLUDE_FILE_CXX("pthread.h" CMAKE_HAVE_PTHREAD_H)
 endif()
-if(CMAKE_HAVE_PTHREAD_H)
 
+if(CMAKE_HAVE_PTHREAD_H)
   #
   # We have pthread.h
   # Let's check for the library now.
@@ -118,13 +141,19 @@ if(CMAKE_HAVE_PTHREAD_H)
   set(CMAKE_HAVE_THREADS_LIBRARY)
   if(NOT THREADS_HAVE_PTHREAD_ARG)
     # Check if pthread functions are in normal C library.
-    CHECK_SYMBOL_EXISTS(pthread_create pthread.h CMAKE_HAVE_LIBC_CREATE)
-    if(CMAKE_HAVE_LIBC_CREATE)
+    # We list some pthread functions in PTHREAD_C_CXX_TEST_SOURCE test code.
+    # If the pthread functions already exist in C library, we could just use
+    # them instead of linking to the additional pthread library.
+    if(CMAKE_C_COMPILER_LOADED)
+      CHECK_C_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD)
+    elseif(CMAKE_CXX_COMPILER_LOADED)
+      CHECK_CXX_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD)
+    endif()
+    if(CMAKE_HAVE_LIBC_PTHREAD)
       set(CMAKE_THREAD_LIBS_INIT "")
       set(CMAKE_HAVE_THREADS_LIBRARY 1)
       set(Threads_FOUND TRUE)
     else()
-
       # Check for -pthread first if enabled. This is the recommended
       # way, but not backwards compatible as one must also pass -pthread
       # as compiler flag then.
@@ -144,7 +173,7 @@ if(CMAKE_HAVE_PTHREAD_H)
   _check_pthreads_flag()
 endif()
 
-if(CMAKE_THREAD_LIBS_INIT OR CMAKE_HAVE_LIBC_CREATE)
+if(CMAKE_THREAD_LIBS_INIT OR CMAKE_HAVE_LIBC_PTHREAD)
   set(CMAKE_USE_PTHREADS_INIT 1)
   set(Threads_FOUND TRUE)
 endif()