Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions src/tbb/cgroup_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,12 @@ class cgroup_info {
}

static bool try_read_cgroup_v1_num_cpus_from(const char* dir, int& num_cpus) {
char path[PATH_MAX] = {0};
if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_quota_us", dir) < 0)
std::size_t pathlen = strlen(dir) + 30;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why +30? The longest addition is only 18 bytes, if I am not mistaken.

std::unique_ptr<char[]> path(new char[pathlen]);
if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_quota_us", dir) < 0)
return false; // Failed to create path

unique_file_t fd(std::fopen(path, "r"), &close_file);
unique_file_t fd(std::fopen(path.get(), "r"), &close_file);
if (!fd)
return false;

Expand All @@ -166,9 +167,10 @@ class cgroup_info {
return true;
}

if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_period_us", dir) < 0)
if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_period_us", dir) < 0)
return false; // Failed to create path;
fd.reset(std::fopen(path, "r"));

fd.reset(std::fopen(path.get(), "r"));
if (!fd)
return false;

Expand All @@ -181,11 +183,12 @@ class cgroup_info {
}

static bool try_read_cgroup_v2_num_cpus_from(const char* dir, int& num_cpus) {
char path[PATH_MAX] = {0};
if (std::snprintf(path, PATH_MAX, "%s/cpu.max", dir) < 0)
std::size_t pathlen = strlen(dir) + 30;
std::unique_ptr<char[]> path(new char[pathlen]);
if (std::snprintf(path.get(), pathlen, "%s/cpu.max", dir) < 0)
return false; // Failed to create path

unique_file_t fd(std::fopen(path, "r"), &close_file);
unique_file_t fd(std::fopen(path.get(), "r"), &close_file);
if (!fd)
return false;

Expand Down Expand Up @@ -222,9 +225,10 @@ class cgroup_info {

static int parse_cgroup_entry(const char* mnt_dir, process_cgroup_data& pcd) {
int num_cpus = error_value; // Initialize to an impossible value
char dir[PATH_MAX] = {0};
if (std::snprintf(dir, PATH_MAX, "%s/%s", mnt_dir, pcd.relative_path) >= 0) {
if (try_read_cgroup_num_cpus_from(dir, num_cpus, pcd.version)) {
std::size_t dirlen = strlen(mnt_dir) + strlen(pcd.relative_path) + 2;
std::unique_ptr<char[]> dir(new char[dirlen]);
if (std::snprintf(dir.get(), dirlen, "%s/%s", mnt_dir, pcd.relative_path) >= 0) {
if (try_read_cgroup_num_cpus_from(dir.get(), num_cpus, pcd.version)) {
return num_cpus;
}
}
Expand Down Expand Up @@ -276,16 +280,20 @@ class cgroup_info {
static int try_common_cgroup_mount_path(const process_cgroup_data& pcd,
const cgroup_settings& cg_cfg) {
int num_cpus = error_value;
char dir[PATH_MAX] = {0};
std::size_t dirlen = (strlen(pcd.relative_path)
+ strlen(cg_cfg.sys_fs_cgroup_dir_path)
+ 25);
std::unique_ptr<char[]> dir(new char[dirlen]);
__TBB_ASSERT(*pcd.relative_path, nullptr);
if (0 <= std::snprintf(dir, PATH_MAX, "%s/%s", cg_cfg.sys_fs_cgroup_dir_path,
if (0 <= std::snprintf(dir.get(), dirlen, "%s/%s",
cg_cfg.sys_fs_cgroup_dir_path,
pcd.relative_path))
try_read_cgroup_num_cpus_from(dir, num_cpus, pcd.version);
try_read_cgroup_num_cpus_from(dir.get(), num_cpus, pcd.version);

if (error_value == num_cpus && pcd.version == process_cgroup_data::cgroup_version::v2) {
if (0 <= std::snprintf(dir, PATH_MAX, "%s/%s", "/sys/fs/cgroup/unified",
if (0 <= std::snprintf(dir.get(), dirlen, "%s/%s", "/sys/fs/cgroup/unified",
pcd.relative_path))
try_read_cgroup_v2_num_cpus_from(dir, num_cpus);
try_read_cgroup_v2_num_cpus_from(dir.get(), num_cpus);
}
return num_cpus;
}
Expand Down
80 changes: 52 additions & 28 deletions src/tbb/dynamic_link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@
#include <wintrust.h>
#pragma comment (lib, "wintrust") // Link with the Wintrust.lib file.
#endif
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#else /* _WIN32 */
#include <dlfcn.h>
#include <unistd.h>
Expand Down Expand Up @@ -177,7 +174,7 @@ namespace r1 {
break;
case dl_buff_too_small:
TBB_FPRINTF(stderr, "%s An internal buffer representing a path to dynamically loaded "
"module is small. Consider compiling with larger value for PATH_MAX macro.\n",
"module is small.\n",
prefix);
break;
case dl_unload_fail:
Expand Down Expand Up @@ -340,12 +337,15 @@ namespace r1 {
static std::once_flag init_dl_data_state;

static struct ap_data_t {
char _path[PATH_MAX+1];
char *_path;
std::size_t _capacity;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is _capacity really need to be saved? If I understand correctly, it only used for doubling the buffer, so probably can be lokal.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I believe it is required on Windows, and for consistency I used it the same way on non-Windows platforms. I was tempted to switch also this to use std::string, but decided against it as std::string is not much used in this library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe it is required on Windows.

I'm not sure in that. It seems it only used to keep value of MAX_PATH and then zeroed in case of unsuccessful allocation. At which part of the code are you talking about?

std::size_t _len;
} ap_data;

static void init_ap_data() {
#if _WIN32
ap_data._capacity = MAX_PATH;
ap_data._path = (char*)calloc(ap_data._capacity, 1);
// Get handle of our DLL first.
HMODULE handle;
BOOL brc = GetModuleHandleEx(
Expand All @@ -356,30 +356,45 @@ namespace r1 {
if ( !brc ) { // Error occurred.
int err = GetLastError();
DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err );
free(ap_data._path);
ap_data._path = NULL;
ap_data._capacity = 0;
return;
}
// Now get path to our DLL.
DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( PATH_MAX ) );
DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( ap_data._capacity ) );
if ( drc == 0 ) { // Error occurred.
int err = GetLastError();
DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err );
free(ap_data._path);
ap_data._path = NULL;
ap_data._capacity = 0;
return;
}
if ( drc >= PATH_MAX ) { // Buffer too short.
if ( drc >= ap_data._capacity ) { // Buffer too short.
DYNAMIC_LINK_WARNING( dl_buff_too_small );
free(ap_data._path);
ap_data._path = NULL;
ap_data._capacity = 0;
return;
}
// Find the position of the last backslash.
char *backslash = std::strrchr( ap_data._path, '\\' );

if ( !backslash ) { // Backslash not found.
__TBB_ASSERT_EX( backslash != nullptr, "Unbelievable.");
free(ap_data._path);
ap_data._path = NULL;
ap_data._capacity = 0;
return;
}
__TBB_ASSERT_EX( backslash >= ap_data._path, "Unbelievable.");
ap_data._len = (std::size_t)(backslash - ap_data._path) + 1;
*(backslash+1) = 0;
#else
// Initial capacity, double until large enough
ap_data._capacity = 4096;
ap_data._path = (char*)calloc(ap_data._capacity, 1);
// There is an use case, when we want to find TBB library, not just some shared object
// providing "dynamic_link" symbol (it can be shared object that directly includes
// dynamic_link.cpp). For this case we use a public TBB symbol. Searching for public symbol
Expand All @@ -397,6 +412,9 @@ namespace r1 {
if ( !res ) {
char const * err = dlerror();
DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err );
free(ap_data._path);
ap_data._path = NULL;
ap_data._capacity = 0;
return;
} else {
__TBB_ASSERT_EX( dlinfo.dli_fname!=nullptr, "Unbelievable." );
Expand All @@ -416,9 +434,14 @@ namespace r1 {
ap_data._len = 0;
} else {
// The library path is relative so get the current working directory
if ( !getcwd( ap_data._path, sizeof(ap_data._path)/sizeof(ap_data._path[0]) ) ) {
DYNAMIC_LINK_WARNING( dl_buff_too_small );
return;
while ( !getcwd( ap_data._path, ap_data._capacity) ) {
free(ap_data._path);
ap_data._capacity *= 2;
ap_data._path = (char*)calloc(ap_data._capacity, 1);
if (NULL == ap_data._path) {
DYNAMIC_LINK_WARNING( dl_buff_too_small );
return;
}
}
ap_data._len = std::strlen( ap_data._path );
ap_data._path[ap_data._len++]='/';
Expand All @@ -427,9 +450,12 @@ namespace r1 {

if ( fname_len>0 ) {
ap_data._len += fname_len;
if ( ap_data._len>PATH_MAX ) {
if ( ap_data._len>ap_data._capacity ) {
DYNAMIC_LINK_WARNING( dl_buff_too_small );
ap_data._len=0;
free(ap_data._path);
ap_data._path = NULL;
ap_data._capacity = 0;
return;
}
std::strncpy( ap_data._path+rc, dlinfo.dli_fname, fname_len );
Expand Down Expand Up @@ -463,7 +489,9 @@ namespace r1 {
if ( full_len < len ) {
__TBB_ASSERT_EX( ap_data._path[ap_data._len] == 0, nullptr );
__TBB_ASSERT_EX( std::strlen(ap_data._path) == ap_data._len, nullptr );
std::strncpy( path, ap_data._path, ap_data._len + 1 );
// No need for strncpy, test above confirmed enough space
// and do not need zero padding at the end.
std::strcpy( path, ap_data._path);
__TBB_ASSERT_EX( path[ap_data._len] == 0, nullptr );
std::strncat( path, name, len - ap_data._len );
__TBB_ASSERT_EX( std::strlen(path) == full_len, nullptr );
Expand Down Expand Up @@ -662,19 +690,18 @@ namespace r1 {
* occurs, in which case the error is optionally reported.
*/
bool has_valid_signature(const char* filepath, const std::size_t length) {
__TBB_ASSERT_EX(length <= PATH_MAX, "Too small buffer for path conversion");
wchar_t wfilepath[PATH_MAX] = {0};
std::unique_ptr<wchar_t[]> wfilepath(new wchar_t[length+1]);
{
std::mbstate_t state{};
const char* ansi_filepath = filepath; // mbsrtowcs moves original pointer
const size_t num_converted = mbsrtowcs(wfilepath, &ansi_filepath, length, &state);
const size_t num_converted = mbsrtowcs(wfilepath.get(), &ansi_filepath, length, &state);
if (num_converted == std::size_t(-1))
return false;
}
WINTRUST_FILE_INFO fdata;
std::memset(&fdata, 0, sizeof(fdata));
fdata.cbStruct = sizeof(WINTRUST_FILE_INFO);
fdata.pcwszFilePath = wfilepath;
fdata.pcwszFilePath = wfilepath.get();

// Check that the certificate used to sign the specified file chains up to a root
// certificate located in the trusted root certificate store, implying that the identity of
Expand Down Expand Up @@ -710,29 +737,26 @@ namespace r1 {
dynamic_link_handle library_handle = nullptr;
#if __TBB_DYNAMIC_LOAD_ENABLED
const char* path = library;
std::size_t const len = PATH_MAX + 1;
char absolute_path[ len ] = {0};
std::size_t len = abs_path(library, NULL, 1);
std::unique_ptr<char[]> absolute_path(new char[len]);
std::size_t length = 0;
const bool build_absolute_path = flags & DYNAMIC_LINK_BUILD_ABSOLUTE_PATH;
if (build_absolute_path) {
length = abs_path( library, absolute_path, len );
if (length > len) {
DYNAMIC_LINK_WARNING( dl_buff_too_small );
return nullptr;
} else if (length == 0) {
length = abs_path( library, absolute_path.get(), len );
if (length == 0) {
// length == 0 means failing of init_ap_data so the warning has already been issued.
return nullptr;
} else if (!file_exists(absolute_path)) {
} else if (!file_exists(absolute_path.get())) {
// Path to a file has been built manually. It is not proven to exist however.
DYNAMIC_LINK_WARNING( dl_lib_not_found, absolute_path, dlerror() );
DYNAMIC_LINK_WARNING( dl_lib_not_found, absolute_path.get(), dlerror() );
return nullptr;
}
path = absolute_path;
path = absolute_path.get();
}
#if _WIN32
#if !__TBB_SKIP_DEPENDENCY_SIGNATURE_VERIFICATION
if (!build_absolute_path) { // Get the path if it is not yet built
length = get_module_path(absolute_path, len, library);
length = get_module_path(absolute_path.get(), (unsigned)len, library);
if (length == 0) {
DYNAMIC_LINK_WARNING( dl_lib_not_found, path, dlerror() );
return library_handle;
Expand All @@ -741,7 +765,7 @@ namespace r1 {
return library_handle;
}
length += 1; // Count terminating NULL character as part of string length
path = absolute_path;
path = absolute_path.get();
}

if (!has_valid_signature(path, length))
Expand Down
4 changes: 2 additions & 2 deletions src/tbb/dynamic_link.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
Copyright (c) 2005-2025 Intel Corporation
Copyright (c) 2026 UXL Foundation Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -132,8 +133,7 @@ enum dynamic_link_error_t : int {
// System call returned error status
dl_sys_fail, // char const * func, dlerr_t err

// Internal intermediate buffer is too small, consider setting PATH_MAX
// macro to a larger value
// Internal intermediate buffer is too small
dl_buff_too_small, // none

// An error during library unload
Expand Down
3 changes: 0 additions & 3 deletions src/tbb/tools_api/ittnotify_static.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
#include "ittnotify_config.h"

#if ITT_PLATFORM==ITT_PLATFORM_WIN
#if !defined(PATH_MAX)
#define PATH_MAX 512
#endif
#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
#include <limits.h>
#include <dlfcn.h>
Expand Down
29 changes: 16 additions & 13 deletions test/common/utils_concurrency_limit.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,12 @@ class cgroup_info {
}

static bool try_read_cgroup_v1_num_cpus_from(const char* dir, int& num_cpus) {
char path[PATH_MAX] = {0};
if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_quota_us", dir) < 0)
std::size_t pathlen = strlen(dir) + 20;
std::unique_ptr<char[]> path(new char[pathlen]);
if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_quota_us", dir) < 0)
return false; // Failed to create path

unique_file_t fd(std::fopen(path, "r"), &close_file);
unique_file_t fd(std::fopen(path.get(), "r"), &close_file);
if (!fd)
return false;

Expand All @@ -224,10 +225,10 @@ class cgroup_info {
return true;
}

if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_period_us", dir) < 0)
if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_period_us", dir) < 0)
return false; // Failed to create path

fd.reset(std::fopen(path, "r"));
fd.reset(std::fopen(path.get(), "r"));
if (!fd)
return false;

Expand All @@ -240,11 +241,12 @@ class cgroup_info {
}

static bool try_read_cgroup_v2_num_cpus_from(const char* dir, int& num_cpus) {
char path[PATH_MAX] = {0};
if (std::snprintf(path, PATH_MAX, "%s/cpu.max", dir) < 0)
std::size_t pathlen = strlen(dir) + 10;
std::unique_ptr<char[]> path(new char[pathlen]);
if (std::snprintf(path.get(), pathlen, "%s/cpu.max", dir) < 0)
return false;

unique_file_t fd(std::fopen(path, "r"), &close_file);
unique_file_t fd(std::fopen(path.get(), "r"), &close_file);
if (!fd)
return false;

Expand Down Expand Up @@ -272,7 +274,8 @@ class cgroup_info {
cgroup_paths& paths_cache)
{
int num_cpus = error_value; // Initialize to an impossible value
char dir[PATH_MAX] = {0};
std::size_t dirlen = strlen(mnt_dir) + rel_path_size + 2;
std::unique_ptr<char[]> dir(new char[dirlen]);
if (!std::strncmp(mnt_type, "cgroup2", 7)) { // Found cgroup v2 mount entry
// At first, try reading CPU quota directly
if (try_read_cgroup_v2_num_cpus_from(mnt_dir, num_cpus))
Expand All @@ -282,8 +285,8 @@ class cgroup_info {
cache_relative_path_for(cgroup_fd, paths_cache);

// Now try reading including relative path
if (std::snprintf(dir, PATH_MAX, "%s/%s", mnt_dir, paths_cache.v2_relative_path) >= 0)
try_read_cgroup_v2_num_cpus_from(dir, num_cpus);
if (std::snprintf(dir.get(), dirlen, "%s/%s", mnt_dir, paths_cache.v2_relative_path) >= 0)
try_read_cgroup_v2_num_cpus_from(dir.get(), num_cpus);
return num_cpus;
}

Expand All @@ -295,8 +298,8 @@ class cgroup_info {
if (!*paths_cache.v1_relative_path)
cache_relative_path_for(cgroup_fd, paths_cache);

if (std::snprintf(dir, PATH_MAX, "%s/%s", mnt_dir, paths_cache.v1_relative_path) >= 0)
try_read_cgroup_v1_num_cpus_from(dir, num_cpus);
if (std::snprintf(dir.get(), dirlen, "%s/%s", mnt_dir, paths_cache.v1_relative_path) >= 0)
try_read_cgroup_v1_num_cpus_from(dir.get(), num_cpus);
return num_cpus;
}

Expand Down
Loading
Loading