/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 |