YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/ulimit_util.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#include "yb/util/ulimit_util.h"
33
34
#include <sys/resource.h>
35
36
#include <map>
37
#include <string>
38
39
#include "yb/util/env.h"
40
#include "yb/util/result.h"
41
#include "yb/util/size_literals.h"
42
#include "yb/util/ulimit.h"
43
44
using std::string;
45
using std::stringstream;
46
using yb::operator"" _KB;
47
using yb::operator"" _MB;
48
49
// These flags allow operators to define process resource soft limits at runtime. Note that on some
50
// systems, RLIM_INFINITY is defined as -1, and setting these flags to that value will result in an
51
// attempt to set these resource limits to infinity. All other negative values are ignored.
52
DEFINE_int64(rlimit_data, RLIM_INFINITY, "Data file size limit: bytes.");
53
#if defined(__APPLE__)
54
// Note that we've chosen 10240 as the default value here since this is the default system limit
55
// for this resource on *macOS* as defined by OPEN_MAX in <sys/syslimits.h>
56
DEFINE_int64(rlimit_nofile, 10240, "Open files limit.");
57
#else
58
DEFINE_int64(rlimit_nofile, 1048576, "Open files limit.");
59
#endif
60
DEFINE_int64(rlimit_fsize, RLIM_INFINITY, "File size limit: blocks.");
61
DEFINE_int64(rlimit_memlock, 64_KB, "Locked memory limit: bytes.");
62
DEFINE_int64(rlimit_as, RLIM_INFINITY, "Memory size limit: bytes.");
63
DEFINE_int64(rlimit_stack, 8_MB, "Stack size limit: bytes.");
64
DEFINE_int64(rlimit_cpu, RLIM_INFINITY, "CPU time limit: seconds.");
65
DEFINE_int64(rlimit_nproc, 12000, "User process limit.");
66
67
// Note: we've observed it can take a while to dump full cores, esp. on systems like kubernetes or
68
// consumer laptops. In order to avoid causing more usability issues, we disable this flag for now
69
// and accept the system default rather than setting this to RLIM_INFINITY as suggested in our
70
// onboarding docs.
71
// DEFINE_int64(rlimit_core, RLIM_INFINITY, "Core file size limit: blocks.");
72
73
namespace {
74
75
const std::map<int, const int64_t&> kRlimitsToInit = {
76
  // {RLIMIT_CORE, FLAGS_rlimit_core},
77
  {RLIMIT_DATA, FLAGS_rlimit_data},
78
  {RLIMIT_NOFILE, FLAGS_rlimit_nofile},
79
  {RLIMIT_FSIZE, FLAGS_rlimit_fsize},
80
  {RLIMIT_MEMLOCK, FLAGS_rlimit_memlock},
81
  {RLIMIT_AS, FLAGS_rlimit_as},
82
  {RLIMIT_STACK, FLAGS_rlimit_stack},
83
  {RLIMIT_CPU, FLAGS_rlimit_cpu},
84
  {RLIMIT_NPROC, FLAGS_rlimit_nproc},
85
};
86
87
const std::map<int, std::string> kRdescriptions = {
88
  {RLIMIT_CORE, "core file size"},
89
  {RLIMIT_DATA, "data seg size"},
90
  {RLIMIT_NOFILE, "open files"},
91
  {RLIMIT_FSIZE, "file size"},
92
  {RLIMIT_MEMLOCK, "max locked memory"},
93
  {RLIMIT_AS, "max memory size"},
94
  {RLIMIT_STACK, "stack size"},
95
  {RLIMIT_CPU, "cpu time"},
96
  {RLIMIT_NPROC, "max user processes"},
97
};
98
99
} // namespace
100
101
namespace yb {
102
103
static stringstream& getLimit(
104
92.9k
    stringstream& ss, const std::string pfx, const std::string sfx, int resource, int rightshift) {
105
92.9k
  ss << "ulimit: " << pfx << " ";
106
92.9k
  const auto limits_or_status = Env::Default()->GetUlimit(resource);
107
92.9k
  if (limits_or_status.ok()) {
108
92.9k
    const ResourceLimit soft = limits_or_status->soft;
109
92.9k
    if (soft.IsUnlimited()) {
110
61.9k
      ss << "unlimited";
111
30.9k
    } else {
112
30.9k
      ss << (soft.RawValue() >> rightshift);
113
30.9k
    }
114
92.9k
    ss << "(";
115
92.9k
    const ResourceLimit hard = limits_or_status->hard;
116
92.9k
    if (hard.IsUnlimited()) {
117
63.0k
      ss << "unlimited";
118
29.9k
    } else {
119
29.9k
      ss << (hard.RawValue() >> rightshift);
120
29.9k
    }
121
92.9k
    ss << ")";
122
0
  } else {
123
0
    ss << "-1";
124
0
  }
125
72.2k
  ss << (sfx[0] ? " " : "") << sfx << "\n";
126
127
92.9k
  return ss;
128
92.9k
}
129
130
175k
static string getCommandLineDescription(int resource) {
131
175k
  if (resource == RLIMIT_CORE) {
132
10.3k
    return "core file size";
133
10.3k
  }
134
165k
  if (resource == RLIMIT_DATA) {
135
20.6k
    return "data seg size";
136
20.6k
  }
137
144k
  if (resource == RLIMIT_NOFILE) {
138
20.6k
    return "open files";
139
20.6k
  }
140
123k
  if (resource == RLIMIT_FSIZE) {
141
20.6k
    return "file size";
142
20.6k
  }
143
#if !defined(__APPLE__)
144
  if (resource == RLIMIT_SIGPENDING) {
145
    return "pending signals";
146
  }
147
  if (resource == RLIMIT_LOCKS) {
148
    return "file locks";
149
  }
150
#endif
151
103k
  if (resource == RLIMIT_MEMLOCK) {
152
20.6k
    return "max locked memory";
153
20.6k
  }
154
82.6k
  if (resource == RLIMIT_AS) {
155
20.6k
    return "max memory size";
156
20.6k
  }
157
61.9k
  if (resource == RLIMIT_STACK) {
158
20.6k
    return "stack size";
159
20.6k
  }
160
41.3k
  if (resource == RLIMIT_CPU) {
161
20.6k
    return "cpu time";
162
20.6k
  }
163
20.6k
  if (resource == RLIMIT_NPROC) {
164
20.6k
    return "max user processes";
165
20.6k
  }
166
0
  return "UNKNOWN";
167
0
}
168
169
10.3k
string UlimitUtil::GetUlimitInfo() {
170
10.3k
  stringstream ss;
171
10.3k
  ss << "\n";
172
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_CORE), "blks", RLIMIT_CORE, 0);
173
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_DATA), "kb", RLIMIT_DATA, 10);
174
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_NOFILE), "", RLIMIT_NOFILE, 0);
175
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_FSIZE), "blks", RLIMIT_FSIZE, 0);
176
#if !defined(__APPLE__)
177
  getLimit(ss, getCommandLineDescription(RLIMIT_SIGPENDING), "", RLIMIT_SIGPENDING, 0);
178
  getLimit(ss, getCommandLineDescription(RLIMIT_LOCKS), "", RLIMIT_LOCKS, 0);
179
#endif
180
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_MEMLOCK), "kb", RLIMIT_MEMLOCK, 10);
181
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_AS), "kb", RLIMIT_AS, 10);
182
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_STACK), "kb", RLIMIT_STACK, 10);
183
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_CPU), "secs", RLIMIT_CPU, 0);
184
10.3k
  getLimit(ss, getCommandLineDescription(RLIMIT_NPROC), "", RLIMIT_NPROC, 0);
185
186
10.3k
  return ss.str();
187
10.3k
}
188
189
10.3k
void UlimitUtil::InitUlimits() {
190
82.6k
  for (const auto& kv : kRlimitsToInit) {
191
82.6k
    int resource_id = kv.first;
192
82.6k
    const ResourceLimit min_soft_limit(kv.second);
193
82.6k
    const string resource_name = getCommandLineDescription(resource_id);
194
195
82.6k
    if (min_soft_limit.IsNegative()) {
196
0
      LOG(INFO)
197
0
          << "Skipping setrlimit for " << resource_name
198
0
          << " with negative specified min value " << min_soft_limit.ToString();
199
0
      continue;
200
0
    }
201
202
82.6k
    const auto limits_or_status = Env::Default()->GetUlimit(resource_id);
203
82.6k
    if (!limits_or_status.ok()) {
204
0
      LOG(ERROR) << "Unable to fetch hard limit for resource " << resource_name
205
0
                 << " Skipping initialization.";
206
0
      continue;
207
0
    }
208
209
82.6k
    const ResourceLimit sys_soft_limit = limits_or_status->soft;
210
82.6k
    if (min_soft_limit <= sys_soft_limit) {
211
61.9k
      LOG(INFO)
212
61.9k
          << "Configured soft limit for " << resource_name
213
61.9k
          << " is already larger than specified min value (" << sys_soft_limit.ToString()
214
61.9k
          << " vs. " << min_soft_limit.ToString() << "). Skipping.";
215
61.9k
      continue;
216
61.9k
    }
217
218
20.6k
    const ResourceLimit sys_hard_limit = limits_or_status->hard;
219
20.6k
    const ResourceLimit new_soft_limit = std::min(sys_hard_limit, min_soft_limit);
220
221
20.6k
    Status set_ulim_status = Env::Default()->SetUlimit(resource_id, new_soft_limit, resource_name);
222
20.6k
    if (!set_ulim_status.ok()) {
223
0
      LOG(ERROR) << "Unable to set new soft limit for resource " << resource_name
224
0
                 << " error: " << set_ulim_status.ToString();
225
0
    }
226
20.6k
  }
227
10.3k
}
228
229
}  // namespace yb