Commit d5331713 authored by Jerry's avatar Jerry
Browse files

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 e9a1ddc5 (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 18320230 (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
parent 2f59cd63
...@@ -38,19 +38,42 @@ This module is not needed for C++11 and later if threading is done using ...@@ -38,19 +38,42 @@ This module is not needed for C++11 and later if threading is done using
#]=======================================================================] #]=======================================================================]
include (CheckLibraryExists) include (CheckLibraryExists)
include (CheckSymbolExists)
set(Threads_FOUND FALSE) set(Threads_FOUND FALSE)
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET ${Threads_FIND_QUIETLY}) set(CMAKE_REQUIRED_QUIET ${Threads_FIND_QUIETLY})
if(CMAKE_C_COMPILER_LOADED) if(CMAKE_C_COMPILER_LOADED)
include (CheckIncludeFile) include (CheckIncludeFile)
include (CheckCSourceCompiles)
elseif(CMAKE_CXX_COMPILER_LOADED) elseif(CMAKE_CXX_COMPILER_LOADED)
include (CheckIncludeFileCXX) include (CheckIncludeFileCXX)
include (CheckCXXSourceCompiles)
else() else()
message(FATAL_ERROR "FindThreads only works if either C or CXX language is enabled") message(FATAL_ERROR "FindThreads only works if either C or CXX language is enabled")
endif() 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. # Internal helper macro.
# Do NOT even think about using it outside of this file! # Do NOT even think about using it outside of this file!
macro(_check_threads_lib LIBNAME FUNCNAME VARNAME) macro(_check_threads_lib LIBNAME FUNCNAME VARNAME)
...@@ -109,8 +132,8 @@ if(CMAKE_C_COMPILER_LOADED) ...@@ -109,8 +132,8 @@ if(CMAKE_C_COMPILER_LOADED)
else() else()
CHECK_INCLUDE_FILE_CXX("pthread.h" CMAKE_HAVE_PTHREAD_H) CHECK_INCLUDE_FILE_CXX("pthread.h" CMAKE_HAVE_PTHREAD_H)
endif() endif()
if(CMAKE_HAVE_PTHREAD_H)
if(CMAKE_HAVE_PTHREAD_H)
# #
# We have pthread.h # We have pthread.h
# Let's check for the library now. # Let's check for the library now.
...@@ -118,13 +141,19 @@ if(CMAKE_HAVE_PTHREAD_H) ...@@ -118,13 +141,19 @@ if(CMAKE_HAVE_PTHREAD_H)
set(CMAKE_HAVE_THREADS_LIBRARY) set(CMAKE_HAVE_THREADS_LIBRARY)
if(NOT THREADS_HAVE_PTHREAD_ARG) if(NOT THREADS_HAVE_PTHREAD_ARG)
# Check if pthread functions are in normal C library. # Check if pthread functions are in normal C library.
CHECK_SYMBOL_EXISTS(pthread_create pthread.h CMAKE_HAVE_LIBC_CREATE) # We list some pthread functions in PTHREAD_C_CXX_TEST_SOURCE test code.
if(CMAKE_HAVE_LIBC_CREATE) # 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_THREAD_LIBS_INIT "")
set(CMAKE_HAVE_THREADS_LIBRARY 1) set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(Threads_FOUND TRUE) set(Threads_FOUND TRUE)
else() else()
# Check for -pthread first if enabled. This is the recommended # Check for -pthread first if enabled. This is the recommended
# way, but not backwards compatible as one must also pass -pthread # way, but not backwards compatible as one must also pass -pthread
# as compiler flag then. # as compiler flag then.
...@@ -144,7 +173,7 @@ if(CMAKE_HAVE_PTHREAD_H) ...@@ -144,7 +173,7 @@ if(CMAKE_HAVE_PTHREAD_H)
_check_pthreads_flag() _check_pthreads_flag()
endif() 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(CMAKE_USE_PTHREADS_INIT 1)
set(Threads_FOUND TRUE) set(Threads_FOUND TRUE)
endif() endif()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment