Do not fail if forkserver is disabled by env when lib_ctor is used

PiperOrigin-RevId: 346743575
Change-Id: I948aad88120746e15535e3c5270581a31a0b3d29
This commit is contained in:
Wiktor Garbacz 2020-12-10 02:49:25 -08:00 committed by Copybara-Service
parent 2869e3f598
commit 6d98090962
5 changed files with 57 additions and 40 deletions

View File

@ -249,6 +249,7 @@ cc_library(
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
deps = [
":fork_client",
":global_forkserver",
"@com_google_absl//absl/base:core_headers",
],

View File

@ -260,6 +260,7 @@ add_library(sandbox2::start_global_forkserver_lib_constructor ALIAS
target_link_libraries(sandbox2_start_global_forkserver_lib_constructor PRIVATE
absl::core_headers
sapi::base
sandbox2::fork_client
sandbox2::global_forkserver
)

View File

@ -116,20 +116,6 @@ GlobalForkserverStartModeSet GetForkserverStartMode() {
}
std::unique_ptr<GlobalForkClient> StartGlobalForkServer() {
if (getenv(kForkServerDisableEnv)) {
SAPI_RAW_VLOG(1,
"Start of the Global Fork-Server prevented by the '%s' "
"environment variable present",
kForkServerDisableEnv);
return {};
}
if (GetForkserverStartMode().empty()) {
SAPI_RAW_VLOG(
1, "Start of the Global Fork-Server prevented by commandline flag");
return {};
}
file_util::fileops::FDCloser exec_fd(
sapi::EmbedFile::GetEmbedFileSingleton()->GetFdForFileToc(
forkserver_bin_embed_create()));
@ -167,10 +153,31 @@ std::unique_ptr<GlobalForkClient> StartGlobalForkServer() {
absl::Mutex GlobalForkClient::instance_mutex_(absl::kConstInit);
GlobalForkClient* GlobalForkClient::instance_ = nullptr;
void GlobalForkClient::EnsureStarted() {
void GlobalForkClient::EnsureStarted(GlobalForkserverStartMode mode) {
absl::MutexLock lock(&instance_mutex_);
EnsureStartedLocked(mode);
}
void GlobalForkClient::EnsureStartedLocked(GlobalForkserverStartMode mode) {
if (!instance_) {
SAPI_RAW_CHECK(!getenv(kForkServerDisableEnv),
"Start of the Global Fork-Server prevented by the '%s' "
"environment variable present",
kForkServerDisableEnv);
SAPI_RAW_CHECK(
GetForkserverStartMode().contains(mode),
"Start of the Global Fork-Server prevented by commandline flag");
instance_ = StartGlobalForkServer().release();
}
SAPI_RAW_CHECK(instance_ != nullptr, "global fork client not initialized");
}
void GlobalForkClient::ForceStart() {
absl::MutexLock lock(&GlobalForkClient::instance_mutex_);
EnsureStartedLocked(
GetForkserverStartMode().contains(GlobalForkserverStartMode::kOnDemand));
SAPI_RAW_CHECK(instance_ == nullptr,
"A force start requested when the Global Fork-Server was "
"already running");
instance_ = StartGlobalForkServer().release();
}
void GlobalForkClient::Shutdown() {
@ -179,19 +186,11 @@ void GlobalForkClient::Shutdown() {
instance_ = nullptr;
}
void GlobalForkClient::EnsureStartedLocked(bool start_if_needed) {
if (!instance_ && start_if_needed) {
instance_ = StartGlobalForkServer().release();
}
SAPI_RAW_CHECK(instance_ != nullptr, "global fork client not initialized");
}
pid_t GlobalForkClient::SendRequest(const ForkRequest& request, int exec_fd,
int comms_fd, int user_ns_fd,
pid_t* init_pid) {
absl::MutexLock lock(&GlobalForkClient::instance_mutex_);
EnsureStartedLocked(
GetForkserverStartMode().contains(GlobalForkserverStartMode::kOnDemand));
EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand);
pid_t pid = instance_->fork_client_.SendRequest(request, exec_fd, comms_fd,
user_ns_fd, init_pid);
if (instance_->comms_.IsTerminated()) {
@ -202,9 +201,7 @@ pid_t GlobalForkClient::SendRequest(const ForkRequest& request, int exec_fd,
pid_t GlobalForkClient::GetPid() {
absl::MutexLock lock(&instance_mutex_);
EnsureStartedLocked(
GetForkserverStartMode().contains(GlobalForkserverStartMode::kOnDemand));
SAPI_RAW_CHECK(instance_ != nullptr, "global fork client not initialized");
EnsureStartedLocked(GlobalForkserverStartMode::kOnDemand);
return instance_->fork_client_.pid();
}
} // namespace sandbox2

View File

@ -33,6 +33,12 @@
namespace sandbox2 {
enum class GlobalForkserverStartMode {
kOnDemand,
// MUST be the last element
kNumGlobalForkserverStartModes,
};
class GlobalForkClient {
public:
GlobalForkClient(int fd, pid_t pid)
@ -44,26 +50,27 @@ class GlobalForkClient {
ABSL_LOCKS_EXCLUDED(instance_mutex_);
static pid_t GetPid() ABSL_LOCKS_EXCLUDED(instance_mutex_);
static void EnsureStarted() ABSL_LOCKS_EXCLUDED(instance_mutex_);
static void EnsureStarted() ABSL_LOCKS_EXCLUDED(instance_mutex_) {
EnsureStarted(GlobalForkserverStartMode::kOnDemand);
}
static void Shutdown() ABSL_LOCKS_EXCLUDED(instance_mutex_);
private:
friend void StartGlobalForkserverFromLibCtor();
static void ForceStart() ABSL_LOCKS_EXCLUDED(instance_mutex_);
static void EnsureStarted(GlobalForkserverStartMode mode)
ABSL_LOCKS_EXCLUDED(instance_mutex_);
static void EnsureStartedLocked(GlobalForkserverStartMode mode)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(instance_mutex_);
static absl::Mutex instance_mutex_;
static GlobalForkClient* instance_ ABSL_GUARDED_BY(instance_mutex_);
static void EnsureStartedLocked(bool start_if_needed = true)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(instance_mutex_);
Comms comms_;
ForkClient fork_client_;
};
enum class GlobalForkserverStartMode {
kOnDemand,
// MUST be the last element
kNumGlobalForkserverStartModes,
};
class GlobalForkserverStartModeSet {
public:
static constexpr size_t kSize = static_cast<size_t>(

View File

@ -12,14 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdlib>
#include "absl/base/attributes.h"
#include "sandboxed_api/sandbox2/fork_client.h"
#include "sandboxed_api/sandbox2/global_forkclient.h"
namespace sandbox2 {
void StartGlobalForkserverFromLibCtor() {
if (!getenv(sandbox2::kForkServerDisableEnv)) {
GlobalForkClient::ForceStart();
}
}
} // namespace sandbox2
// Run the ForkServer from the constructor, when no other threads are present.
// Because it's possible to start thread-inducing initializers before
// RunInitializers() (base/googleinit.h) it's not enough to just register
// a 0000_<name> initializer instead.
ABSL_ATTRIBUTE_UNUSED
__attribute__((constructor)) static void StartSandbox2Forkserver() {
sandbox2::GlobalForkClient::EnsureStarted();
sandbox2::StartGlobalForkserverFromLibCtor();
}