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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@
# *******************************************************************************
load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
name = "configure_process",
srcs = ["configure_process.cpp"],
hdrs = ["configure_process.hpp"],
include_prefix = "score/mw/launch_manager/process_group_manager/details",
strip_include_prefix = "/score/launch_manager/src/daemon/src/process_group_manager/details",
visibility = ["//score/launch_manager/src/daemon/src/process_group_manager:__pkg__"],
deps = [
"//score/launch_manager/src/daemon/src/osal:return_types",
"//score/launch_manager/src/daemon/src/osal:security_policy",
"//score/launch_manager/src/daemon/src/osal:set_affinity",
"//score/launch_manager/src/daemon/src/osal:set_groups",
"//score/launch_manager/src/daemon/src/osal:sys_exit",
"//score/launch_manager/src/daemon/src/process_group_manager:iprocess",
],
)

cc_library(
name = "process_info_node",
hdrs = ["process_info_node.hpp"],
Expand Down Expand Up @@ -98,13 +115,10 @@ cc_library(
srcs = ["process_launcher.cpp"],
visibility = ["//score/launch_manager/src/daemon/src/process_group_manager:__pkg__"],
deps = [
":configure_process",
"//score/launch_manager/src/daemon/src/common:log",
"//score/launch_manager/src/daemon/src/control:control_client_channel",
"//score/launch_manager/src/daemon/src/osal:ipc_comms",
"//score/launch_manager/src/daemon/src/osal:security_policy",
"//score/launch_manager/src/daemon/src/osal:set_affinity",
"//score/launch_manager/src/daemon/src/osal:set_groups",
"//score/launch_manager/src/daemon/src/osal:sys_exit",
"//score/launch_manager/src/daemon/src/process_group_manager:iprocess",
],
)
Expand All @@ -121,6 +135,7 @@ cc_library(
],
visibility = ["//score/launch_manager/src/daemon/src/process_group_manager:__pkg__"],
deps = [
":configure_process",
":graph",
":os_handler",
":process_info_node",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/********************************************************************************
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

#include <limits.h>

#include <libgen.h>
#include <sys/resource.h>
#include <cerrno>
#include <cstring>
#include <string>
#include <string_view>

#include "score/launch_manager/src/daemon/src/osal/return_types.hpp"
#include "score/mw/launch_manager/osal/security_policy.hpp"
#include "score/mw/launch_manager/osal/set_affinity.hpp"
#include "score/mw/launch_manager/osal/set_groups.hpp"
#include "score/mw/launch_manager/process_group_manager/iprocess.hpp"

namespace score
{

namespace lcm
{

namespace internal
{

void setLimit(const int resource, const std::size_t amount, const std::string_view rlimit_name) noexcept
{
if (amount == 0U)
{
return;
}

const struct rlimit limit{
.rlim_cur = amount,
.rlim_max = amount,
};

const auto result = ::setrlimit(resource, &limit);
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(
result != -1, ("Failed to set rlimit " + std::string(rlimit_name) + ": " + std::strerror(errno)).c_str());
}

void setSchedulingAndSecurity(const osal::OsalConfig& config)
{
int result; // Used for return value from system calls

// Set process group id to be equal to the pid
// setpgid will fail if called by a session leader (which LCMd is), so skip
if (config.comms_type_ != osal::CommsType::kLaunchManager)
{
result = setpgid(0, getpid());
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result == 0, std::strerror(errno));
}

// Set scheduling policy with sched_setscheduler
/* RULECHECKER_comment(1, 1, check_union_object, "Union type defined in external library is used.", true) */
sched_param sch_param{};

sch_param.sched_priority = config.scheduling_priority_;

// TODO: Clamping should be done when the config is loaded
if (sch_param.sched_priority < sched_get_priority_min(config.scheduling_policy_))
{
sch_param.sched_priority = sched_get_priority_min(config.scheduling_policy_);
}
else if (sch_param.sched_priority > sched_get_priority_max(config.scheduling_policy_))
{
sch_param.sched_priority = sched_get_priority_max(config.scheduling_policy_);
}

result = sched_setscheduler(0, config.scheduling_policy_, &sch_param);
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result != -1, std::strerror(errno));

result = osal::setaffinity(config.cpu_mask_);
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result != -1, std::strerror(errno));

result = setgid(config.gid_);
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result != -1, std::strerror(errno));

// Note: the type of the first parameter of setgroups() differs in Linux and QNX, so we use osal
const auto gids_size = config.supplementary_gids_.size();
if (gids_size > 0)
{
const auto gids_data = config.supplementary_gids_.data();
result = osal::setgroups(gids_size, gids_data);
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result != -1, std::strerror(errno));
}

result = setuid(config.uid_);
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result != -1, std::strerror(errno));
}

void changeCurrentWorkingDirectory(const osal::OsalConfig& config)
{
// Change current working directory to the same as the executable
constexpr size_t string_size = static_cast<size_t>(PATH_MAX);
// Notice that this next static variable is duplicated by the fork() and so does not need
// any protection by a mutex although at first sight you may think it could need one.
static char path_copy[string_size + 1U] = {0};

// TODO: This should be validated when the config is loaded
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(config.executable_path_.size() < string_size,
"Executable path is too long");

const auto result = chdir(dirname(strncpy(path_copy, config.executable_path_.c_str(), string_size)));
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(result != -1, std::strerror(errno));
}

void implementMemoryResourceLimits(const osal::OsalConfig& config)
{
setLimit(RLIMIT_DATA, config.resource_limits_.data_, "RLIMIT_DATA");
setLimit(RLIMIT_AS, config.resource_limits_.as_, "RLIMIT_AS");
setLimit(RLIMIT_STACK, config.resource_limits_.stack_, "RLIMIT_STACK");

// Note about cpu limit:
// Using setrlimit, this imposes a maximum time that a process will run for, which might not be
// what you intend? Probably you'll want a maximum time in a time-slice, but you don't get that
// with limits set by setrlimit...
setLimit(RLIMIT_CPU, config.resource_limits_.cpu_, "RLIMIT_CPU");
}

void changeSecurityPolicy(const osal::OsalConfig& config)
{
if (config.security_policy_ != "")
{
const auto result = osal::setSecurityPolicy(config.security_policy_.c_str());
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(
result == 0,
("Changing security policy to " + config.security_policy_ + ": " + std::strerror(errno)).c_str());
}
}

} // namespace internal

} // namespace lcm

} // namespace score
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/********************************************************************************
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

#include <string_view>

#include "score/mw/launch_manager/osal/security_policy.hpp"
#include "score/mw/launch_manager/process_group_manager/iprocess.hpp"

namespace score
{

namespace lcm
{

namespace internal
{

/// @brief Sets the limit if given a non-zero value, otherwise skips.
/// @warning This will abort if not successful.
void setLimit(const int resource, const std::size_t amount, const std::string_view rlimit_name);

/// @warning This will abort if not successful.
void setSchedulingAndSecurity(const osal::OsalConfig& config);

/// @warning This will abort if not successful.
void changeCurrentWorkingDirectory(const osal::OsalConfig& config);

/// @warning This will abort if not successful.
void implementMemoryResourceLimits(const osal::OsalConfig& config);

/// @warning This will abort if not successful.
void changeSecurityPolicy(const osal::OsalConfig& config);

} // namespace internal

} // namespace lcm

} // namespace score
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <unistd.h>
#include <csignal>

#include "score/launch_manager/src/daemon/src/process_group_manager/details/configure_process.hpp"
#include "score/mw/launch_manager/common/log.hpp"
#include "score/mw/launch_manager/process_group_manager/ialive_monitor_thread.hpp"
#include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp"
Expand Down Expand Up @@ -104,10 +105,9 @@ bool ProcessGroupManager::initialize()
return false;
}

if (launch_manager_config_ &&
OsalReturnType::kFail == IProcess::setSchedulingAndSecurity(launch_manager_config_->startup_config_))
if (launch_manager_config_)
{
return false;
setSchedulingAndSecurity(launch_manager_config_->startup_config_);
}

return true;
Expand Down
Loading
Loading