From 98dc81e87df05e518fdefec7333fa8841f4cb56e Mon Sep 17 00:00:00 2001 From: Jose Santiago Date: Tue, 31 Aug 2021 12:02:28 +0200 Subject: [PATCH 1/2] [core] Detect pthread_getname* availability --- CMakeLists.txt | 3 ++ scripts/FindPThreadGetSetName.cmake | 82 +++++++++++++++++++++++++++++ srtcore/srt_attr_defs.h | 2 +- srtcore/threadname.h | 57 ++++++++++++++++---- 4 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 scripts/FindPThreadGetSetName.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d817261a..8cbee7d3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,6 +275,9 @@ if (DEFINED HAVE_INET_PTON) add_definitions(-DHAVE_INET_PTON=1) endif() +include(FindPThreadGetSetName) +FindPThreadGetSetName() # Defines HAVE_PTHREAD_GETNAME_* and HAVE_PTHREAD_SETNAME_* + if (ENABLE_MONOTONIC_CLOCK) if (NOT ENABLE_MONOTONIC_CLOCK_DEFAULT) message(FATAL_ERROR "Your platform does not support CLOCK_MONOTONIC. Build with -DENABLE_MONOTONIC_CLOCK=OFF.") diff --git a/scripts/FindPThreadGetSetName.cmake b/scripts/FindPThreadGetSetName.cmake new file mode 100644 index 000000000..fa818fd73 --- /dev/null +++ b/scripts/FindPThreadGetSetName.cmake @@ -0,0 +1,82 @@ +# +# SRT - Secure, Reliable, Transport +# Copyright (c) 2021 Haivision Systems Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# Check for pthread_getname_np(3) and pthread_setname_np(3) +# used in srtcore/threadname.h. +# +# Some BSD distros need to include for pthread_getname_np(). +# +# TODO: Some BSD distros have pthread_get_name_np() and pthread_set_name_np() +# instead of pthread_getname_np() and pthread_setname_np(). +# +# Sets: +# HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +# HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +# HAVE_PTHREAD_GETNAME_NP +# HAVE_PTHREAD_SETNAME_NP +# Sets as appropriate: +# add_definitions(-DHAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H=1) +# add_definitions(-DHAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H=1) +# add_definitions(-DHAVE_PTHREAD_GETNAME_NP=1) +# add_definitions(-DHAVE_PTHREAD_SETNAME_NP=1) + +include(CheckSymbolExists) + +function(FindPThreadGetSetName) + + unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H PARENT_SCOPE) + unset(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H CACHE) + unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H PARENT_SCOPE) + unset(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H CACHE) + + unset(HAVE_PTHREAD_GETNAME_NP) + unset(HAVE_PTHREAD_GETNAME_NP PARENT_SCOPE) + unset(HAVE_PTHREAD_GETNAME_NP CACHE) + unset(HAVE_PTHREAD_SETNAME_NP) + unset(HAVE_PTHREAD_SETNAME_NP PARENT_SCOPE) + unset(HAVE_PTHREAD_SETNAME_NP CACHE) + + set(CMAKE_REQUIRED_DEFINITIONS + -D_GNU_SOURCE -D_DARWIN_C_SOURCE -D_POSIX_SOURCE=1) + set(CMAKE_REQUIRED_FLAGS "-pthread") + + message(STATUS "Checking for pthread_(g/s)etname_np in 'pthread_np.h':") + check_symbol_exists( + pthread_getname_np "pthread_np.h" HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + if (HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + add_definitions(-DHAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H=1) + endif() + check_symbol_exists( + pthread_setname_np "pthread_np.h" HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + if (HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + add_definitions(-DHAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H=1) + endif() + + message(STATUS "Checking for pthread_(g/s)etname_np in 'pthread.h':") + check_symbol_exists(pthread_getname_np "pthread.h" HAVE_PTHREAD_GETNAME_NP) + if (HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) + set(HAVE_PTHREAD_GETNAME_NP TRUE PARENT_SCOPE) + endif() + check_symbol_exists(pthread_setname_np "pthread.h" HAVE_PTHREAD_SETNAME_NP) + if (HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + set(HAVE_PTHREAD_SETNAME_NP TRUE PARENT_SCOPE) + endif() + if (HAVE_PTHREAD_GETNAME_NP) + add_definitions(-DHAVE_PTHREAD_GETNAME_NP=1) + endif() + if (HAVE_PTHREAD_SETNAME_NP) + add_definitions(-DHAVE_PTHREAD_SETNAME_NP=1) + endif() + + unset(CMAKE_REQUIRED_DEFINITIONS) + unset(CMAKE_REQUIRED_FLAGS) + +endfunction(FindPThreadGetSetName) diff --git a/srtcore/srt_attr_defs.h b/srtcore/srt_attr_defs.h index 82e6e5e3a..00d35e069 100644 --- a/srtcore/srt_attr_defs.h +++ b/srtcore/srt_attr_defs.h @@ -116,7 +116,7 @@ used by SRT library internally. #define SRT_ATTR_NO_THREAD_SAFETY_ANALYSIS #else -#if defined(__clang__) +#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ > 5) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op diff --git a/srtcore/threadname.h b/srtcore/threadname.h index 2b3964276..e392f6d8e 100644 --- a/srtcore/threadname.h +++ b/srtcore/threadname.h @@ -16,24 +16,60 @@ written by #ifndef INC_SRT_THREADNAME_H #define INC_SRT_THREADNAME_H -#if defined(__APPLE__) || defined(__linux__) -#if defined(__linux__) -#include +// NOTE: +// HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H +// HAVE_PTHREAD_GETNAME_NP +// HAVE_PTHREAD_GETNAME_NP +// Are detected and set in ../CMakeLists.txt. +// OS Availability of pthread_getname_np(..) and pthread_setname_np(..):: +// MacOS(10.6) +// iOS(3.2) +// AIX(7.1) +// FreeBSD(version?), OpenBSD(Version?) +// Linux-GLIBC(GLIBC-2.12). +// Linux-MUSL(MUSL-1.1.20 Partial Implementation. See below). +// MINGW-W64(4.0.6) + +#if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + || defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) + #include + #if defined(HAVE_PTHREAD_GETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_GETNAME_NP) + #define HAVE_PTHREAD_GETNAME_NP 1 + #endif + #if defined(HAVE_PTHREAD_SETNAME_NP_IN_PTHREAD_NP_H) \ + && !defined(HAVE_PTHREAD_SETNAME_NP) + #define HAVE_PTHREAD_SETNAME_NP 1 + #endif #endif -#include +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) + // NOTE: + // Linux pthread_getname_np() and pthread_setname_np() became available + // in GLIBC-2.12 and later. + // Some Linux runtimes do not have pthread_getname_np(), but have + // pthread_setname_np(), for instance MUSL at least as of v1.1.20. + // So using the prctl() for Linux is more portable. + #if defined(__linux__) + #include + #endif + #include #endif #include #include #include +#include "common.h" #include "sync.h" class ThreadName { -#if defined(__APPLE__) || defined(__linux__) +#if (defined(HAVE_PTHREAD_GETNAME_NP) && defined(HAVE_PTHREAD_GETNAME_NP)) \ + || defined(__linux__) class ThreadNameImpl { @@ -47,8 +83,7 @@ class ThreadName // since Linux 2.6.11. The buffer should allow space for up to 16 // bytes; the returned string will be null-terminated. return prctl(PR_GET_NAME, (unsigned long)namebuf, 0, 0) != -1; -#elif defined(__APPLE__) - // since macos(10.6), ios(3.2) +#elif defined(HAVE_PTHREAD_GETNAME_NP) return pthread_getname_np(pthread_self(), namebuf, BUFSIZE) == 0; #else #error "unsupported platform" @@ -57,14 +92,18 @@ class ThreadName static bool set(const char* name) { + SRT_ASSERT(name != NULL); #if defined(__linux__) // The name can be up to 16 bytes long, including the terminating // null byte. (If the length of the string, including the terminating // null byte, exceeds 16 bytes, the string is silently truncated.) return prctl(PR_SET_NAME, (unsigned long)name, 0, 0) != -1; -#elif defined(__APPLE__) - // since macos(10.6), ios(3.2) +#elif defined(HAVE_PTHREAD_SETNAME_NP) + #if defined(__APPLE__) return pthread_setname_np(name) == 0; + #else + return pthread_setname_np(pthread_self(), name) == 0; + #endif #else #error "unsupported platform" #endif From 0e4f9f836fd53b21dee81c19e5d09f22be32b119 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Tue, 31 Aug 2021 16:27:03 +0200 Subject: [PATCH 2/2] [core] Placed ThreadName class inside srt namespace --- apps/srt-tunnel.cpp | 18 +++++++++--------- srtcore/threadname.h | 4 ++++ test/test_threadname.cpp | 2 ++ testing/srt-test-multiplex.cpp | 10 +++++----- testing/srt-test-relay.cpp | 4 ++-- testing/testactivemedia.cpp | 4 ++-- testing/testactivemedia.hpp | 2 +- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/apps/srt-tunnel.cpp b/apps/srt-tunnel.cpp index 2c4aacfb3..fd25fb998 100644 --- a/apps/srt-tunnel.cpp +++ b/apps/srt-tunnel.cpp @@ -223,17 +223,17 @@ class Engine Engine(Tunnel* p, Medium* m1, Medium* m2, const std::string& nid) : #ifdef HAVE_FULL_CXX11 - media {m1, m2}, + media {m1, m2}, #endif - parent_tunnel(p), nameid(nid) + parent_tunnel(p), nameid(nid) { #ifndef HAVE_FULL_CXX11 - // MSVC is not exactly C++11 compliant and complains around - // initialization of an array. - // Leaving this method of initialization for clarity and - // possibly more preferred performance. - media[0] = m1; - media[1] = m2; + // MSVC is not exactly C++11 compliant and complains around + // initialization of an array. + // Leaving this method of initialization for clarity and + // possibly more preferred performance. + media[0] = m1; + media[1] = m2; #endif } @@ -241,7 +241,7 @@ class Engine { Verb() << "START: " << media[DIR_IN]->uri() << " --> " << media[DIR_OUT]->uri(); std::string thrn = media[DIR_IN]->id() + ">" + media[DIR_OUT]->id(); - ThreadName tn(thrn.c_str()); + srt::ThreadName tn(thrn.c_str()); thr = thread([this]() { Worker(); }); } diff --git a/srtcore/threadname.h b/srtcore/threadname.h index e392f6d8e..a3dbb475e 100644 --- a/srtcore/threadname.h +++ b/srtcore/threadname.h @@ -65,6 +65,8 @@ written by #include "common.h" #include "sync.h" +namespace srt { + class ThreadName { @@ -217,4 +219,6 @@ class ThreadName } }; +} // namespace srt + #endif diff --git a/test/test_threadname.cpp b/test/test_threadname.cpp index f9b1d1d8c..67301f97b 100644 --- a/test/test_threadname.cpp +++ b/test/test_threadname.cpp @@ -4,6 +4,8 @@ #include "gtest/gtest.h" #include "threadname.h" +using namespace srt; + TEST(ThreadName, GetSet) { std::string name("getset"); diff --git a/testing/srt-test-multiplex.cpp b/testing/srt-test-multiplex.cpp index 859547069..e2d5c8b89 100644 --- a/testing/srt-test-multiplex.cpp +++ b/testing/srt-test-multiplex.cpp @@ -154,14 +154,14 @@ struct MediumPair applog.Note() << sout.str(); } } - catch (Source::ReadEOF& x) + catch (const Source::ReadEOF&) { applog.Note() << "EOS - closing media for loop: " << name; src->Close(); tar->Close(); applog.Note() << "CLOSED: " << name; } - catch (std::runtime_error& x) + catch (const std::runtime_error& x) { applog.Note() << "INTERRUPTED: " << x.what(); src->Close(); @@ -196,7 +196,7 @@ class MediaBase med.name = name; // Ok, got this, so we can start transmission. - ThreadName tn(thread_name.c_str()); + srt::ThreadName tn(thread_name.c_str()); med.runner = thread( [&med]() { med.TransmissionLoop(); }); return med; @@ -577,7 +577,7 @@ int main( int argc, char** argv ) SrtModel m(up.host(), iport, up.parameters()); - ThreadName::set("main"); + srt::ThreadName::set("main"); // Note: for input, there must be an exactly defined // number of sources. The loop rolls up to all these sources. @@ -615,7 +615,7 @@ int main( int argc, char** argv ) break; } - ThreadName::set("main"); + srt::ThreadName::set("main"); } applog.Note() << "All local stream definitions covered. Waiting for interrupt/broken all connections."; diff --git a/testing/srt-test-relay.cpp b/testing/srt-test-relay.cpp index 1214125b7..323718b51 100755 --- a/testing/srt-test-relay.cpp +++ b/testing/srt-test-relay.cpp @@ -392,7 +392,7 @@ SrtMainLoop::SrtMainLoop(const string& srt_uri, bool input_echoback, const strin void SrtMainLoop::InputRunner() { - ThreadName::set("InputRN"); + srt::ThreadName::set("InputRN"); // An extra thread with a loop that reads from the external input // and writes into the SRT medium. When echoback mode is used, // this thread isn't started at all and instead the SRT reading @@ -438,7 +438,7 @@ void SrtMainLoop::run() std::ostringstream tns; tns << "Input:" << this; - ThreadName tn(tns.str().c_str()); + srt::ThreadName tn(tns.str().c_str()); m_input_thr = thread([this] { try { InputRunner(); diff --git a/testing/testactivemedia.cpp b/testing/testactivemedia.cpp index 765d22ef6..53f42a9a1 100644 --- a/testing/testactivemedia.cpp +++ b/testing/testactivemedia.cpp @@ -3,7 +3,7 @@ void SourceMedium::Runner() { - ThreadName::set("SourceRN"); + srt::ThreadName::set("SourceRN"); Verb() << VerbLock << "Starting SourceMedium: " << this; for (;;) @@ -63,7 +63,7 @@ MediaPacket SourceMedium::Extract() void TargetMedium::Runner() { - ThreadName::set("TargetRN"); + srt::ThreadName::set("TargetRN"); auto on_return_set = OnReturnSet(running, false); Verb() << VerbLock << "Starting TargetMedium: " << this; for (;;) diff --git a/testing/testactivemedia.hpp b/testing/testactivemedia.hpp index 06a1cd922..fbb2f9dc8 100644 --- a/testing/testactivemedia.hpp +++ b/testing/testactivemedia.hpp @@ -58,7 +58,7 @@ struct Medium running = true; std::ostringstream tns; tns << typeid(*this).name() << ":" << this; - ThreadName tn(tns.str().c_str()); + srt::ThreadName tn(tns.str().c_str()); thr = thread( [this] { RunnerBase(); } ); }