Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

thead pool debugging support proposal using native capabilities if po… #3628

Merged
merged 1 commit into from
Sep 30, 2023

Conversation

devnexen
Copy link
Collaborator

…ssible.

@devnexen devnexen force-pushed the thread_pool_debug branch 3 times, most recently from b91f69d to f53b820 Compare July 15, 2023 07:31
@coveralls
Copy link

coveralls commented Jul 15, 2023

Coverage Status

coverage: 91.753% (+0.01%) from 91.743% when pulling 313e439 on thread_pool_debug into ae37d65 on master.

#if defined(BOTAN_TARGET_OS_IS_LINUX)
r = pthread_setname_np(hdl, name);
#elif defined(BOTAN_TARGET_OS_IS_FREEBSD)
r = pthread_set_name_np(hdl, name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FreeBSD also seems to support pthead_setname_np (https://man.freebsd.org/cgi/man.cgi?query=pthread_set_name_np) which would reduce the number of conditionals.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we consider windows the only exception in term of supporting EOL releases then yes.

@@ -148,6 +152,10 @@ void page_allow_access(void* page);
*/
void page_named(void* page, size_t size);

#if defined(BOTAN_TARGET_OS_HAS_THREADS)
void set_thread_name(std::thread& thread, const char* const name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required (by any OS) that this point to static storage? If so that should be documented here. Otherwise, name should be a const std::string& instead of a C style string.

(I would say a std::string_view but you can't convert that to a NULL terminated string)

#elif defined(BOTAN_TARGET_OS_IS_FREEBSD)
r = pthread_set_name_np(hdl, name);
#elif defined(BOTAN_TARGET_OS_IS_OPENBSD)
r = pthread_set_name_np(hdl, const_cast<char*>(name));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast doesn't seem to be necessary? (https://man.openbsd.org/pthread_set_name_np)

#elif defined(BOTAN_TARGET_OS_IS_OPENBSD)
r = pthread_set_name_np(hdl, const_cast<char*>(name));
#elif defined(BOTAN_TARGET_OS_IS_NETBSD)
r = pthread_set_name_np(hdl, "%s", const_cast<char*>(name));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What a weird interface

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair point, you end up 99% of the time with a string anyway..

// also gives a chance to be in coredumps.
wchar_t val[16];
if(MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, name, -1, val, 16) > 0) {
r = SetThreadDescription(hdl, val);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription this function is only supported on Windows 10 or higher, which I think would be problematic

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general the policy is that we don't support operating systems that are no longer supported by the OS vendor, but for Windows we are basically forced to be more lax than that simply due to the huge installed base of out of date systems.

I think practically speaking we are limited to using features that are available in the oldest version of Windows that is supported by the oldest version of VC++ we support. For VC that's VC2022 now. But I can't find anything definite about the oldest OS that VC2022 will allow you to target. I know we reverted #365 because people were still building XP-compatible binaries in 2016.

int r;
auto hdl = thread.native_handle();
#if defined(BOTAN_TARGET_OS_IS_LINUX)
r = pthread_setname_np(hdl, name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of assigning to r and then using BOTAN_UNUSED later on in the function just static_cast<void>(pthread_set...) within each block.

#if defined(BOTAN_TARGET_OS_HAS_THREADS)
void OS::set_thread_name(std::thread& thread, const char* const name) {
int r;
auto hdl = thread.native_handle();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::thread::native_handle isn't necessarily guaranteed to exist, which would cause this to fail to compile on a (probably weird) OS that supported threads but didn't let you access native handles.

Instead call thread.native_handle() within each block which ensures we only call it if we have some idea what OS we are on.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah right I thought HAS_THREADS meant "all the way", fair enough then.

@devnexen devnexen force-pushed the thread_pool_debug branch 3 times, most recently from 4229e6b to 02fb333 Compare July 15, 2023 22:07
#elif defined(BOTAN_TARGET_OS_IS_NETBSD)
static_cast<void>(pthread_set_name_np(thread.native_handle(), "%s", const_cast<char*>(name.c_str())));
#elif defined(BOTAN_TARGET_OS_HAS_WIN32) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
const DWORD MS_VC_EXCEPTION = 0x406D1388;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach doesn't seem so useful since it's works if you are currently attached to a debugger.

If it's possible to check at compile time what the target OS is, I'd suggest calling the Windows 10 function if it is available and for older systems just do nothing. If that's not possible I'd say just remove this block entirely and leave a comment that we can use SetThreadDescription in the future.

In 33dee2f I deprecated support for older Windows but we'll probably want to wait at least a release or two before pulling the trigger on it.

Copy link
Owner

@randombit randombit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This is looking very good now. I left a few comments.

@@ -148,6 +152,10 @@ void page_allow_access(void* page);
*/
void page_named(void* page, size_t size);

#if defined(BOTAN_TARGET_OS_HAS_THREADS)
void set_thread_name(std::thread& thread, std::string& name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I guess name cannot be a string_view since we need to get the null terminated value, so I think it should be a const std::string&

@@ -41,6 +41,8 @@ Thread_Pool& Thread_Pool::global_instance() {

Thread_Pool::Thread_Pool(std::optional<size_t> opt_pool_size) {
m_shutdown = false;
// On Linux, it is 16 length max, including terminator
std::string tname = "Botan thread";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be const

#elif defined(BOTAN_TARGET_OS_IS_NETBSD)
static_cast<void>(pthread_set_name_np(thread.native_handle(), "%s", const_cast<char*>(name.c_str())));
#elif defined(BOTAN_TARGET_OS_HAS_WIN32) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
// Using SetThreadDescription from Win10
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a BOTAN_UNUSED here as well - currently Windows CI is failing because the parameters are not used

// TODO other possible oses ?
// macOs does not seem to allow to name threads other than the current one.
BOTAN_UNUSED(thread);
BOTAN_UNUSED(name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can pass multiple args to a single invocation of BOTAN_UNUSED - BOTAN_UNUSED(thread, name)

Copy link
Owner

@randombit randombit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Thanks for addressing the review comments.

@randombit randombit added this to the Botan 3.2.0 milestone Sep 30, 2023
@devnexen devnexen merged commit 86381e7 into master Sep 30, 2023
38 checks passed
@randombit randombit deleted the thread_pool_debug branch October 5, 2023 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants