blob: 6446c1418349a0c3cb12d66db7d607e4cf06662d [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sys/time.h>
#include <sys/types.h>
// Intentionally include `sys/resource.h` after `sys/time.h` and
// `sys/types.h`. This is the suggested include pattern under e.g.,
// BSD, https://www.freebsd.org/cgi/man.cgi?query=setrlimit.
#include <sys/resource.h>
#include <stout/os/strerror.hpp>
#include <stout/unreachable.hpp>
#include "posix/rlimits.hpp"
namespace mesos {
namespace internal {
namespace rlimits {
Try<int> convert(RLimitInfo::RLimit::Type type)
{
const Error error(
"Resource type '" + RLimitInfo_RLimit_Type_Name(type) +
"' not supported");
switch (type) {
// Resource types defined in XSI.
case RLimitInfo::RLimit::RLMT_AS: return RLIMIT_AS;
case RLimitInfo::RLimit::RLMT_CORE: return RLIMIT_CORE;
case RLimitInfo::RLimit::RLMT_CPU: return RLIMIT_CPU;
case RLimitInfo::RLimit::RLMT_DATA: return RLIMIT_DATA;
case RLimitInfo::RLimit::RLMT_FSIZE: return RLIMIT_FSIZE;
case RLimitInfo::RLimit::RLMT_NOFILE: return RLIMIT_NOFILE;
case RLimitInfo::RLimit::RLMT_STACK: return RLIMIT_STACK;
// Resource types also defined on BSDs like e.g., OS X.
case RLimitInfo::RLimit::RLMT_MEMLOCK: return RLIMIT_MEMLOCK;
case RLimitInfo::RLimit::RLMT_NPROC: return RLIMIT_NPROC;
case RLimitInfo::RLimit::RLMT_RSS: return RLIMIT_RSS;
// Resource types defined in >=Linux 2.6.36.
// NOTE: The resource limits defined for Linux are currently the
// maximal possible set of understood types. Here we explicitly
// list all types and in particular do not use a `default` case,
// see MESOS-3754.
case RLimitInfo::RLimit::RLMT_LOCKS:
#ifdef RLIMIT_LOCKS
return RLIMIT_LOCKS;
#else
return error;
#endif
case RLimitInfo::RLimit::RLMT_MSGQUEUE:
#ifdef RLIMIT_MSGQUEUE
return RLIMIT_MSGQUEUE;
#else
return error;
#endif
case RLimitInfo::RLimit::RLMT_NICE:
#ifdef RLIMIT_NICE
return RLIMIT_NICE;
#else
return error;
#endif
case RLimitInfo::RLimit::RLMT_RTPRIO:
#ifdef RLIMIT_RTPRIO
return RLIMIT_RTPRIO;
#else
return error;
#endif
case RLimitInfo::RLimit::RLMT_RTTIME:
#ifdef RLIMIT_RTTIME
return RLIMIT_RTTIME;
#else
return error;
#endif
case RLimitInfo::RLimit::RLMT_SIGPENDING:
#ifdef RLIMIT_SIGPENDING
return RLIMIT_SIGPENDING;
#else
return error;
#endif
case RLimitInfo::RLimit::UNKNOWN:
return Error("Unknown rlimit type");
}
UNREACHABLE();
}
Try<Nothing> set(const RLimitInfo::RLimit& limit)
{
const Try<int> resource = convert(limit.type());
if (resource.isError()) {
return Error("Could not convert rlimit: " + resource.error());
}
::rlimit resourceLimit;
if (limit.has_soft() && limit.has_hard()) {
resourceLimit.rlim_cur = limit.soft();
resourceLimit.rlim_max = limit.hard();
} else if (!limit.has_soft() && !limit.has_hard()) {
resourceLimit.rlim_cur = RLIM_INFINITY;
resourceLimit.rlim_max = RLIM_INFINITY;
} else {
return Error("Invalid rlimit values");
}
if (setrlimit(resource.get(), &resourceLimit) != 0) {
return Error("Failed to set rlimit: " + os::strerror(errno));
}
return Nothing();
}
} // namespace rlimits {
} // namespace internal {
} // namespace mesos {