Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: third_party/crashpad/crashpad/util/posix/close_multiple.cc

Issue 2478633002: Update Crashpad to b47bf6c250c6b825dee1c5fbad9152c2c962e828 (Closed)
Patch Set: mac comment 2 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "util/posix/close_multiple.h" 15 #include "util/posix/close_multiple.h"
16 16
17 #include <dirent.h> 17 #include <dirent.h>
18 #include <errno.h> 18 #include <errno.h>
19 #include <fcntl.h> 19 #include <fcntl.h>
20 #include <limits.h> 20 #include <limits.h>
21 #include <stdio.h>
21 #include <stdlib.h> 22 #include <stdlib.h>
22 #include <string.h> 23 #include <string.h>
23 #include <unistd.h> 24 #include <unistd.h>
24 25
25 #include <algorithm> 26 #include <algorithm>
26 #include <memory> 27 #include <memory>
27 28
29 #include "base/files/scoped_file.h"
28 #include "base/logging.h" 30 #include "base/logging.h"
29 #include "base/posix/eintr_wrapper.h" 31 #include "base/posix/eintr_wrapper.h"
30 #include "build/build_config.h" 32 #include "build/build_config.h"
31 #include "util/misc/implicit_cast.h" 33 #include "util/misc/implicit_cast.h"
32 #include "util/numeric/safe_assignment.h" 34 #include "util/numeric/safe_assignment.h"
33 35
36 #if defined(OS_MACOSX)
37 #include <sys/sysctl.h>
38 #endif
39
34 // Everything in this file is expected to execute between fork() and exec(), 40 // Everything in this file is expected to execute between fork() and exec(),
35 // so everything called here must be acceptable in this context. However, 41 // so everything called here must be acceptable in this context. However,
36 // logging code that is not expected to execute under normal circumstances is 42 // logging code that is not expected to execute under normal circumstances is
37 // currently permitted. 43 // currently permitted.
38 44
39 namespace crashpad { 45 namespace crashpad {
40 namespace { 46 namespace {
41 47
42 // This function attempts to close |fd| or mark it as close-on-exec. On systems 48 // This function attempts to close |fd| or mark it as close-on-exec. On systems
43 // where close-on-exec is attempted, a failure to mark it close-on-exec will be 49 // where close-on-exec is attempted, a failure to mark it close-on-exec will be
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 81
76 using ScopedDIR = std::unique_ptr<DIR, ScopedDIRCloser>; 82 using ScopedDIR = std::unique_ptr<DIR, ScopedDIRCloser>;
77 83
78 // This function implements CloseMultipleNowOrOnExec() using an operating 84 // This function implements CloseMultipleNowOrOnExec() using an operating
79 // system-specific FD directory to determine which file descriptors are open. 85 // system-specific FD directory to determine which file descriptors are open.
80 // This is an advantage over looping over all possible file descriptors, because 86 // This is an advantage over looping over all possible file descriptors, because
81 // no attempt needs to be made to close file descriptors that are not open. 87 // no attempt needs to be made to close file descriptors that are not open.
82 bool CloseMultipleNowOrOnExecUsingFDDir(int fd, int preserve_fd) { 88 bool CloseMultipleNowOrOnExecUsingFDDir(int fd, int preserve_fd) {
83 #if defined(OS_MACOSX) 89 #if defined(OS_MACOSX)
84 const char kFDDir[] = "/dev/fd"; 90 const char kFDDir[] = "/dev/fd";
85 #elif defined(OS_LINUX) 91 #elif defined(OS_LINUX) || defined(OS_ANDROID)
86 const char kFDDir[] = "/proc/self/fd"; 92 const char kFDDir[] = "/proc/self/fd";
87 #endif 93 #endif
88 94
89 DIR* dir = opendir(kFDDir); 95 DIR* dir = opendir(kFDDir);
90 if (!dir) { 96 if (!dir) {
91 PLOG(WARNING) << "opendir"; 97 PLOG(WARNING) << "opendir";
92 return false; 98 return false;
93 } 99 }
94 100
95 ScopedDIR dir_owner(dir); 101 ScopedDIR dir_owner(dir);
96 102
97 int dir_fd = dirfd(dir); 103 int dir_fd = dirfd(dir);
98 if (dir_fd == -1) { 104 if (dir_fd == -1) {
99 PLOG(WARNING) << "dirfd"; 105 PLOG(WARNING) << "dirfd";
100 return false; 106 return false;
101 } 107 }
102 108
109 dirent* result;
110 #if defined(OS_LINUX)
111 // readdir_r() is deprecated as of glibc 2.24. See
112 // https://sourceware.org/bugzilla/show_bug.cgi?id=19056 and
113 // https://git.kernel.org/cgit/docs/man-pages/man-pages.git/commit?id=0c52f6d6 23636a61eacd0f7b7a3bb942793a2a05.
114 const char kReaddirName[] = "readdir";
115 while ((errno = 0, result = readdir(dir)) != nullptr)
116 #else
117 const char kReaddirName[] = "readdir_r";
103 dirent entry; 118 dirent entry;
104 dirent* result; 119 while ((errno = readdir_r(dir, &entry, &result)) == 0 && result != nullptr)
105 int rv; 120 #endif
106 while ((rv = readdir_r(dir, &entry, &result)) == 0 && result != nullptr) { 121 {
107 const char* entry_name = &(*result->d_name); 122 const char* entry_name = &(*result->d_name);
108 if (strcmp(entry_name, ".") == 0 || strcmp(entry_name, "..") == 0) { 123 if (strcmp(entry_name, ".") == 0 || strcmp(entry_name, "..") == 0) {
109 continue; 124 continue;
110 } 125 }
111 126
112 char* end; 127 char* end;
113 long entry_fd_long = strtol(entry_name, &end, 10); 128 long entry_fd_long = strtol(entry_name, &end, 10);
114 if (entry_name[0] == '\0' || *end) { 129 if (entry_name[0] == '\0' || *end) {
115 LOG(ERROR) << "unexpected entry " << entry_name; 130 LOG(ERROR) << "unexpected entry " << entry_name;
116 return false; 131 return false;
117 } 132 }
118 133
119 int entry_fd; 134 int entry_fd;
120 if (!AssignIfInRange(&entry_fd, entry_fd_long)) { 135 if (!AssignIfInRange(&entry_fd, entry_fd_long)) {
121 LOG(ERROR) << "out-of-range fd " << entry_name; 136 LOG(ERROR) << "out-of-range fd " << entry_name;
122 return false; 137 return false;
123 } 138 }
124 139
125 if (entry_fd >= fd && entry_fd != preserve_fd && entry_fd != dir_fd) { 140 if (entry_fd >= fd && entry_fd != preserve_fd && entry_fd != dir_fd) {
126 CloseNowOrOnExec(entry_fd, false); 141 CloseNowOrOnExec(entry_fd, false);
127 } 142 }
128 } 143 }
129 144
145 if (errno != 0) {
146 PLOG(WARNING) << kReaddirName;
147 return false;
148 }
149
130 return true; 150 return true;
131 } 151 }
132 152
133 } // namespace 153 } // namespace
134 154
135 void CloseMultipleNowOrOnExec(int fd, int preserve_fd) { 155 void CloseMultipleNowOrOnExec(int fd, int preserve_fd) {
136 if (CloseMultipleNowOrOnExecUsingFDDir(fd, preserve_fd)) { 156 if (CloseMultipleNowOrOnExecUsingFDDir(fd, preserve_fd)) {
137 return; 157 return;
138 } 158 }
139 159
140 // Fallback: close every file descriptor starting at |fd| and ending at the 160 // Fallback: close every file descriptor starting at |fd| and ending at the
141 // system’s file descriptor limit. Check a few values and use the highest as 161 // system’s file descriptor limit. Check a few values and use the highest as
142 // the limit, because these may be based on the file descriptor limit set by 162 // the limit, because these may be based on the file descriptor limit set by
143 // setrlimit(), and higher-numbered file descriptors may have been opened 163 // setrlimit(), and higher-numbered file descriptors may have been opened
144 // prior to the limit being lowered. For Mac OS X, see 10.9.2 164 // prior to the limit being lowered. On both macOS and Linux glibc, both
145 // Libc-997.90.3/gen/FreeBSD/sysconf.c sysconf() and 10.9.4 165 // sysconf() and getdtablesize() return the current RLIMIT_NOFILE value, not
146 // xnu-2422.110.17/bsd/kern/kern_descrip.c getdtablesize(), which both return 166 // the maximum possible file descriptor. For macOS, see 10.11.5
147 // the current RLIMIT_NOFILE value, not the maximum possible file descriptor. 167 // Libc-1082.50.1/gen/FreeBSD/sysconf.c sysconf() and 10.11.6
148 int max_fd = std::max(implicit_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); 168 // xnu-3248.60.10/bsd/kern/kern_descrip.c getdtablesize(). For Linux glibc,
169 // see glibc-2.24/sysdeps/posix/sysconf.c __sysconf() and
170 // glibc-2.24/sysdeps/posix/getdtsz.c __getdtablesize(). For Android, see
171 // 7.0.0 bionic/libc/bionic/sysconf.cpp sysconf() and
172 // bionic/libc/bionic/ndk_cruft.cpp getdtablesize().
173 int max_fd = implicit_cast<int>(sysconf(_SC_OPEN_MAX));
174
175 #if !defined(OS_ANDROID)
176 // getdtablesize() was removed effective Android 5.0.0 (API 21). Since it
177 // returns the same thing as the sysconf() above, just skip it. See
178 // https://android.googlesource.com/platform/bionic/+/462abab12b074c62c0999859 e65d5a32ebb41951.
149 max_fd = std::max(max_fd, getdtablesize()); 179 max_fd = std::max(max_fd, getdtablesize());
180 #endif
181
182 #if !defined(OS_LINUX) || defined(OPEN_MAX)
183 // Linux does not provide OPEN_MAX. See
184 // https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit /include/linux/limits.h?id=77293034696e3e0b6c8b8fc1f96be091104b3d2b.
185 max_fd = std::max(max_fd, OPEN_MAX);
186 #endif
187
188 // Consult a sysctl to determine the system-wide limit on the maximum number
189 // of open files per process. Note that it is possible to change this limit
190 // while the system is running, but it’s still a better upper bound than the
191 // current RLIMIT_NOFILE value.
192
193 #if defined(OS_MACOSX)
194 // See 10.11.6 xnu-3248.60.10/bsd/kern/kern_resource.c maxfilesperproc,
195 // referenced by dosetrlimit().
196 int oid[] = {CTL_KERN, KERN_MAXFILESPERPROC};
197 int maxfilesperproc;
198 size_t maxfilesperproc_size = sizeof(maxfilesperproc);
199 if (sysctl(oid,
200 arraysize(oid),
201 &maxfilesperproc,
202 &maxfilesperproc_size,
203 nullptr,
204 0) == 0) {
205 max_fd = std::max(max_fd, maxfilesperproc);
206 } else {
207 PLOG(WARNING) << "sysctl";
208 }
209 #elif defined(OS_LINUX) || defined(OS_ANDROID)
210 // See linux-4.4.27/fs/file.c sysctl_nr_open, referenced by kernel/sys.c
211 // do_prlimit() and kernel/sysctl.c fs_table. Inability to open this file is
212 // not considered an error, because /proc may not be available or usable.
213 {
214 base::ScopedFILE nr_open_file(fopen("/proc/sys/fs/nr_open", "r"));
215 if (nr_open_file.get() != nullptr) {
216 int nr_open;
217 if (fscanf(nr_open_file.get(), "%d\n", &nr_open) == 1 &&
218 feof(nr_open_file.get())) {
219 max_fd = std::max(max_fd, nr_open);
220 } else {
221 LOG(WARNING) << "/proc/sys/fs/nr_open format error";
222 }
223 }
224 }
225 #endif
150 226
151 for (int entry_fd = fd; entry_fd < max_fd; ++entry_fd) { 227 for (int entry_fd = fd; entry_fd < max_fd; ++entry_fd) {
152 if (entry_fd != preserve_fd) { 228 if (entry_fd != preserve_fd) {
153 CloseNowOrOnExec(entry_fd, true); 229 CloseNowOrOnExec(entry_fd, true);
154 } 230 }
155 } 231 }
156 } 232 }
157 233
158 } // namespace crashpad 234 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698