OLD | NEW |
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, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 } | 70 } |
71 } | 71 } |
72 }; | 72 }; |
73 | 73 |
74 typedef scoped_ptr<DIR, ScopedDIRCloser> ScopedDIR; | 74 typedef scoped_ptr<DIR, ScopedDIRCloser> ScopedDIR; |
75 | 75 |
76 // This function implements CloseMultipleNowOrOnExec() using an operating | 76 // This function implements CloseMultipleNowOrOnExec() using an operating |
77 // system-specific FD directory to determine which file descriptors are open. | 77 // system-specific FD directory to determine which file descriptors are open. |
78 // This is an advantage over looping over all possible file descriptors, because | 78 // This is an advantage over looping over all possible file descriptors, because |
79 // no attempt needs to be made to close file descriptors that are not open. | 79 // no attempt needs to be made to close file descriptors that are not open. |
80 bool CloseMultipleNowOrOnExecUsingFDDir(int fd) { | 80 bool CloseMultipleNowOrOnExecUsingFDDir(int fd, int preserve_fd) { |
81 #if defined(OS_MACOSX) | 81 #if defined(OS_MACOSX) |
82 const char kFDDir[] = "/dev/fd"; | 82 const char kFDDir[] = "/dev/fd"; |
83 #elif defined(OS_LINUX) | 83 #elif defined(OS_LINUX) |
84 const char kFDDir[] = "/proc/self/fd"; | 84 const char kFDDir[] = "/proc/self/fd"; |
85 #endif | 85 #endif |
86 | 86 |
87 DIR* dir = opendir(kFDDir); | 87 DIR* dir = opendir(kFDDir); |
88 if (!dir) { | 88 if (!dir) { |
89 PLOG(WARNING) << "opendir"; | 89 PLOG(WARNING) << "opendir"; |
90 return false; | 90 return false; |
(...skipping 22 matching lines...) Expand all Loading... |
113 LOG(ERROR) << "unexpected entry " << entry_name; | 113 LOG(ERROR) << "unexpected entry " << entry_name; |
114 return false; | 114 return false; |
115 } | 115 } |
116 | 116 |
117 int entry_fd; | 117 int entry_fd; |
118 if (!AssignIfInRange(&entry_fd, entry_fd_long)) { | 118 if (!AssignIfInRange(&entry_fd, entry_fd_long)) { |
119 LOG(ERROR) << "out-of-range fd " << entry_name; | 119 LOG(ERROR) << "out-of-range fd " << entry_name; |
120 return false; | 120 return false; |
121 } | 121 } |
122 | 122 |
123 if (entry_fd >= fd && entry_fd != dir_fd) { | 123 if (entry_fd >= fd && entry_fd != preserve_fd && entry_fd != dir_fd) { |
124 CloseNowOrOnExec(entry_fd, false); | 124 CloseNowOrOnExec(entry_fd, false); |
125 } | 125 } |
126 } | 126 } |
127 | 127 |
128 return true; | 128 return true; |
129 } | 129 } |
130 | 130 |
131 } // namespace | 131 } // namespace |
132 | 132 |
133 void CloseMultipleNowOrOnExec(int fd) { | 133 void CloseMultipleNowOrOnExec(int fd, int preserve_fd) { |
134 if (CloseMultipleNowOrOnExecUsingFDDir(fd)) { | 134 if (CloseMultipleNowOrOnExecUsingFDDir(fd, preserve_fd)) { |
135 return; | 135 return; |
136 } | 136 } |
137 | 137 |
138 // Fallback: close every file descriptor starting at |fd| and ending at the | 138 // Fallback: close every file descriptor starting at |fd| and ending at the |
139 // system’s file descriptor limit. Check a few values and use the highest as | 139 // system’s file descriptor limit. Check a few values and use the highest as |
140 // the limit, because these may be based on the file descriptor limit set by | 140 // the limit, because these may be based on the file descriptor limit set by |
141 // setrlimit(), and higher-numbered file descriptors may have been opened | 141 // setrlimit(), and higher-numbered file descriptors may have been opened |
142 // prior to the limit being lowered. For Mac OS X, see 10.9.2 | 142 // prior to the limit being lowered. For Mac OS X, see 10.9.2 |
143 // Libc-997.90.3/gen/FreeBSD/sysconf.c sysconf() and 10.9.4 | 143 // Libc-997.90.3/gen/FreeBSD/sysconf.c sysconf() and 10.9.4 |
144 // xnu-2422.110.17/bsd/kern/kern_descrip.c getdtablesize(), which both return | 144 // xnu-2422.110.17/bsd/kern/kern_descrip.c getdtablesize(), which both return |
145 // the current RLIMIT_NOFILE value, not the maximum possible file descriptor. | 145 // the current RLIMIT_NOFILE value, not the maximum possible file descriptor. |
146 int max_fd = std::max(static_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); | 146 int max_fd = std::max(static_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); |
147 max_fd = std::max(max_fd, getdtablesize()); | 147 max_fd = std::max(max_fd, getdtablesize()); |
148 | 148 |
149 for (int entry_fd = fd; entry_fd < max_fd; ++entry_fd) { | 149 for (int entry_fd = fd; entry_fd < max_fd; ++entry_fd) { |
150 CloseNowOrOnExec(entry_fd, true); | 150 if (entry_fd != preserve_fd) { |
| 151 CloseNowOrOnExec(entry_fd, true); |
| 152 } |
151 } | 153 } |
152 } | 154 } |
153 | 155 |
154 } // namespace crashpad | 156 } // namespace crashpad |
OLD | NEW |