fd.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 51 Filedescriptor Functions */
10
11#include "squid.h"
12#include "comm/Loops.h"
13#include "debug/Messages.h"
14#include "debug/Stream.h"
16#include "fatal.h"
17#include "fd.h"
18#include "fde.h"
19#include "globals.h"
20
21// Solaris and possibly others lack MSG_NOSIGNAL optimization
22// TODO: move this into compat/? Use a dedicated compat file to avoid dragging
23// sys/socket.h into the rest of Squid??
24#ifndef MSG_NOSIGNAL
25#define MSG_NOSIGNAL 0
26#endif
27
28int default_read_method(int, char *, int);
29int default_write_method(int, const char *, int);
30#if _SQUID_WINDOWS_
31int socket_read_method(int, char *, int);
32int socket_write_method(int, const char *, int);
33int file_read_method(int, char *, int);
34int file_write_method(int, const char *, int);
35#else
36int msghdr_read_method(int, char *, int);
37int msghdr_write_method(int, const char *, int);
38#endif
39
40const char *fdTypeStr[] = {
41 "None",
42 "Log",
43 "File",
44 "Socket",
45 "Pipe",
46 "MsgHdr",
47 "Unknown"
48};
49
50static void fdUpdateBiggest(int fd, int);
51
52static void
53fdUpdateBiggest(int fd, int opening)
54{
55 if (fd < Biggest_FD)
56 return;
57
58 assert(fd < Squid_MaxFD);
59
60 if (fd > Biggest_FD) {
61 /*
62 * assert that we are not closing a FD bigger than
63 * our known biggest FD
64 */
65 assert(opening);
66 Biggest_FD = fd;
67 return;
68 }
69
70 /* if we are here, then fd == Biggest_FD */
71 /*
72 * assert that we are closing the biggest FD; we can't be
73 * re-opening it
74 */
75 assert(!opening);
76
77 while (Biggest_FD >= 0 && !fd_table[Biggest_FD].flags.open)
78 --Biggest_FD;
79}
80
81void
82fd_close(int fd)
83{
84 fde *F = &fd_table[fd];
85
86 assert(fd >= 0);
87 assert(F->flags.open);
88
89 if (F->type == FD_FILE) {
90 assert(F->read_handler == nullptr);
91 assert(F->write_handler == nullptr);
92 }
93
94 debugs(51, 3, "fd_close FD " << fd << " " << F->desc);
96 F->flags.open = false;
97 fdUpdateBiggest(fd, 0);
98 --Number_FD;
99 F->clear();
100}
101
102#if _SQUID_WINDOWS_
103
104int
105socket_read_method(int fd, char *buf, int len)
106{
107 return recv(fd, (void *) buf, len, 0);
108}
109
110int
111file_read_method(int fd, char *buf, int len)
112{
113 return _read(fd, buf, len);
114}
115
116int
117socket_write_method(int fd, const char *buf, int len)
118{
119 return send(fd, (const void *) buf, len, 0);
120}
121
122int
123file_write_method(int fd, const char *buf, int len)
124{
125 return _write(fd, buf, len);
126}
127
128#else
129int
130default_read_method(int fd, char *buf, int len)
131{
132 return read(fd, buf, len);
133}
134
135int
136default_write_method(int fd, const char *buf, int len)
137{
138 return write(fd, buf, len);
139}
140
141int
142msghdr_read_method(int fd, char *buf, int)
143{
144 return recvmsg(fd, reinterpret_cast<msghdr*>(buf), MSG_DONTWAIT);
145}
146
147int
148msghdr_write_method(int fd, const char *buf, int len)
149{
150 const int i = sendmsg(fd, reinterpret_cast<const msghdr*>(buf), MSG_NOSIGNAL);
151 return i > 0 ? len : i; // len is imprecise but the caller expects a match
152}
153
154#endif
155
156void
157fd_open(int fd, unsigned int type, const char *desc)
158{
159 fde *F;
160 assert(fd >= 0);
161 F = &fd_table[fd];
162
163 if (F->flags.open) {
164 debugs(51, DBG_IMPORTANT, "WARNING: Closing open FD " << std::setw(4) << fd);
165 fd_close(fd);
166 }
167
168 assert(!F->flags.open);
169 debugs(51, 3, "fd_open() FD " << fd << " " << desc);
170 F->type = type;
171 F->flags.open = true;
172 F->epoll_state = 0;
173#if _SQUID_WINDOWS_
174
175 F->win32.handle = _get_osfhandle(fd);
176
177 switch (type) {
178
179 case FD_SOCKET:
180
181 case FD_PIPE:
182 F->setIo(&socket_read_method, &socket_write_method);
183 break;
184
185 case FD_FILE:
186
187 case FD_LOG:
188 F->setIo(&file_read_method, &file_write_method);
189 break;
190
191 default:
192 fatalf("fd_open(): unknown FD type - FD#: %i, type: %u, desc %s\n", fd, type, desc);
193 }
194
195#else
196 switch (type) {
197
198 case FD_MSGHDR:
200 break;
201
202 default:
204 break;
205 }
206
207#endif
208
209 fdUpdateBiggest(fd, 1);
210
211 fd_note(fd, desc);
212
213 ++Number_FD;
214}
215
216void
217fd_note(int fd, const char *s)
218{
219 fde *F = &fd_table[fd];
220 if (s)
221 xstrncpy(F->desc, s, FD_DESC_SZ);
222 else
223 *(F->desc) = 0; // ""-string
224}
225
226void
227fd_bytes(int fd, int len, unsigned int type)
228{
229 fde *F = &fd_table[fd];
230
231 if (len < 0)
232 return;
233
234 assert(type == FD_READ || type == FD_WRITE);
235
236 if (type == FD_READ)
237 F->bytes_read += len;
238 else
239 F->bytes_written += len;
240}
241
242void
244{
245 int i;
246 fde *F;
247
248 for (i = 0; i < Squid_MaxFD; ++i) {
249 F = &fd_table[i];
250
251 if (!F->flags.open)
252 continue;
253
254 if (i == fileno(debug_log))
255 continue;
256
257 debugs(51, Important(17), "Open FD "<< std::left<< std::setw(10) <<
258 (F->bytes_read && F->bytes_written ? "READ/WRITE" :
259 F->bytes_read ? "READING" : F->bytes_written ? "WRITING" :
260 "UNSTARTED") <<
261 " "<< std::right << std::setw(4) << i << " " << F->desc);
262 }
263}
264
265int
267{
269}
270
271int
273{
274 int nrfree = fdNFree();
275
276 if (nrfree < (RESERVED_FD << 1))
277 return 1;
278
279 if (nrfree < (Number_FD >> 2))
280 return 1;
281
282 return 0;
283}
284
285/* Called when we runs out of file descriptors */
286void
288{
289 int newReserve;
290 int x;
291 static time_t last = 0;
292 /*
293 * don't update too frequently
294 */
295
296 if (last + 5 > squid_curtime)
297 return;
298
299 /*
300 * Calculate a new reserve, based on current usage and a small extra
301 */
302 newReserve = Squid_MaxFD - Number_FD + min(25, Squid_MaxFD / 16);
303
304 if (newReserve <= RESERVED_FD)
305 return;
306
307 x = Squid_MaxFD - 20 - min(25, Squid_MaxFD / 16);
308
309 if (newReserve > x) {
310 /* perhaps this should be fatal()? -DW */
311 debugs(51, DBG_CRITICAL, "WARNING: This machine has a serious shortage of filedescriptors.");
312 newReserve = x;
313 }
314
315 if (Squid_MaxFD - newReserve < min(256, Squid_MaxFD / 2))
316 fatalf("Too few filedescriptors available in the system (%d usable of %d).\n", Squid_MaxFD - newReserve, Squid_MaxFD);
317
318 debugs(51, DBG_CRITICAL, "Reserved FD adjusted from " << RESERVED_FD << " to " << newReserve <<
319 " due to failures (" << (Squid_MaxFD - newReserve) << "/" << Squid_MaxFD << " file descriptors available)");
320 RESERVED_FD = newReserve;
321}
322
323/* Comm::Descriptor */
324
325Comm::Descriptor::Descriptor(const int fd, const unsigned int type, const char * const description): fd_(fd)
326{
327 fd_open(fd_, type, description);
328}
329
331{
332 if (fd_ >= 0) {
333 fd_close(fd_);
334 if (close(fd_) != 0) {
335 const auto savedErrno = errno;
336 debugs(51, 7, "failed to close FD " << fd_ << ReportSysError(savedErrno));
337 }
338 }
339}
340
time_t squid_curtime
Definition: stub_libtime.cc:20
#define assert(EX)
Definition: assert.h:19
int fd_
Definition: fd.h:37
Descriptor(int fd, unsigned int type, const char *description)
Definition: fd.cc:325
~Descriptor()
Closes and calls legacy fd_close() unless release() was called earlier.
Definition: fd.cc:330
a stream manipulator for printing a system call error (if any)
Definition: fde.h:52
A const & min(A const &lhs, A const &rhs)
#define Important(id)
Definition: Messages.h:91
#define DBG_IMPORTANT
Definition: Stream.h:41
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
#define debug_log
change-avoidance macro; new code should call DebugStream() instead
Definition: Stream.h:185
#define DBG_CRITICAL
Definition: Stream.h:40
#define FD_DESC_SZ
Definition: defines.h:32
@ FD_SOCKET
Definition: enums.h:16
@ FD_FILE
Definition: enums.h:15
@ FD_LOG
Definition: enums.h:14
@ FD_PIPE
Definition: enums.h:17
@ FD_MSGHDR
Definition: enums.h:18
@ FD_WRITE
Definition: enums.h:24
@ FD_READ
Definition: enums.h:23
int type
Definition: errorpage.cc:152
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
int default_read_method(int, char *, int)
Definition: fd.cc:130
void fd_close(int fd)
Definition: fd.cc:82
void fd_note(int fd, const char *s)
Definition: fd.cc:217
int fdNFree(void)
Definition: fd.cc:266
const char * fdTypeStr[]
Definition: fd.cc:40
int msghdr_read_method(int, char *, int)
Definition: fd.cc:142
int default_write_method(int, const char *, int)
Definition: fd.cc:136
void fdAdjustReserved(void)
Definition: fd.cc:287
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:227
void fd_open(int fd, unsigned int type, const char *desc)
Definition: fd.cc:157
static void fdUpdateBiggest(int fd, int)
Definition: fd.cc:53
#define MSG_NOSIGNAL
Definition: fd.cc:25
void fdDumpOpen(void)
Definition: fd.cc:243
int fdUsageHigh(void)
Definition: fd.cc:272
int msghdr_write_method(int, const char *, int)
Definition: fd.cc:148
#define fd_table
Definition: fde.h:189
int Opening_FD
int Squid_MaxFD
int Number_FD
int RESERVED_FD
int Biggest_FD
static uint32 F(uint32 X, uint32 Y, uint32 Z)
Definition: md4.c:46
void ResetSelect(int fd)
reset/undo/unregister the watch for an FD which was set by Comm::SetSelect()
Definition: Loops.h:30
static char last
Definition: parse.c:451
Definition: cmsg.h:88
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors