Squid Web Cache master
Loading...
Searching...
No Matches
fd.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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 "compat/socket.h"
14#include "compat/unistd.h"
15#include "debug/Messages.h"
16#include "debug/Stream.h"
17#include "fatal.h"
18#include "fd.h"
19#include "fde.h"
20#include "globals.h"
21
22int default_read_method(int, char *, int);
23int default_write_method(int, const char *, int);
24#if _SQUID_WINDOWS_
25int socket_read_method(int, char *, int);
26int socket_write_method(int, const char *, int);
27int file_read_method(int, char *, int);
28int file_write_method(int, const char *, int);
29#else
30int msghdr_read_method(int, char *, int);
31int msghdr_write_method(int, const char *, int);
32#endif
33
34const char *fdTypeStr[] = {
35 "None",
36 "Log",
37 "File",
38 "Socket",
39 "Pipe",
40 "MsgHdr",
41 "Unknown"
42};
43
44static void fdUpdateBiggest(int fd, int);
45
46static void
47fdUpdateBiggest(int fd, int opening)
48{
49 if (fd < Biggest_FD)
50 return;
51
52 assert(fd < Squid_MaxFD);
53
54 if (fd > Biggest_FD) {
55 /*
56 * assert that we are not closing a FD bigger than
57 * our known biggest FD
58 */
59 assert(opening);
60 Biggest_FD = fd;
61 return;
62 }
63
64 /* if we are here, then fd == Biggest_FD */
65 /*
66 * assert that we are closing the biggest FD; we can't be
67 * re-opening it
68 */
69 assert(!opening);
70
71 while (Biggest_FD >= 0 && !fd_table[Biggest_FD].flags.open)
72 --Biggest_FD;
73}
74
75void
76fd_close(int fd)
77{
78 fde *F = &fd_table[fd];
79
80 assert(fd >= 0);
81 assert(F->flags.open);
82
83 if (F->type == FD_FILE) {
84 assert(F->read_handler == nullptr);
85 assert(F->write_handler == nullptr);
86 }
87
88 debugs(51, 3, "fd_close FD " << fd << " " << F->desc);
90 F->flags.open = false;
91 fdUpdateBiggest(fd, 0);
92 --Number_FD;
93 F->clear();
94}
95
96#if _SQUID_WINDOWS_
97
98int
99socket_read_method(int fd, char *buf, int len)
100{
101 return xrecv(fd, (void *) buf, len, 0);
102}
103
104int
105file_read_method(int fd, char *buf, int len)
106{
107 return _read(fd, buf, len);
108}
109
110int
111socket_write_method(int fd, const char *buf, int len)
112{
113 return xsend(fd, buf, len, 0);
114}
115
116int
117file_write_method(int fd, const char *buf, int len)
118{
119 return _write(fd, buf, len);
120}
121
122#else
123int
124default_read_method(int fd, char *buf, int len)
125{
126 return xread(fd, buf, len);
127}
128
129int
130default_write_method(int fd, const char *buf, int len)
131{
132 return xwrite(fd, buf, len);
133}
134
135int
136msghdr_read_method(int fd, char *buf, int)
137{
138 return recvmsg(fd, reinterpret_cast<msghdr*>(buf), MSG_DONTWAIT);
139}
140
141int
142msghdr_write_method(int fd, const char *buf, int len)
143{
144 const int i = sendmsg(fd, reinterpret_cast<const msghdr*>(buf), MSG_NOSIGNAL);
145 return i > 0 ? len : i; // len is imprecise but the caller expects a match
146}
147
148#endif
149
150void
151fd_open(int fd, unsigned int type, const char *desc)
152{
153 fde *F;
154 assert(fd >= 0);
155 F = &fd_table[fd];
156
157 if (F->flags.open) {
158 debugs(51, DBG_IMPORTANT, "WARNING: Closing open FD " << std::setw(4) << fd);
159 fd_close(fd);
160 }
161
162 assert(!F->flags.open);
163 debugs(51, 3, "fd_open() FD " << fd << " " << desc);
164 F->type = type;
165 F->flags.open = true;
166 F->epoll_state = 0;
167#if _SQUID_WINDOWS_
168
169 F->win32.handle = _get_osfhandle(fd);
170
171 switch (type) {
172
173 case FD_SOCKET:
174
175 case FD_PIPE:
176 F->setIo(&socket_read_method, &socket_write_method);
177 break;
178
179 case FD_FILE:
180
181 case FD_LOG:
182 F->setIo(&file_read_method, &file_write_method);
183 break;
184
185 default:
186 fatalf("fd_open(): unknown FD type - FD#: %i, type: %u, desc %s\n", fd, type, desc);
187 }
188
189#else
190 switch (type) {
192 case FD_MSGHDR:
194 break;
195
196 default:
198 break;
199 }
200
201#endif
202
203 fdUpdateBiggest(fd, 1);
204
205 fd_note(fd, desc);
206
207 ++Number_FD;
208}
209
210void
211fd_note(int fd, const char *s)
212{
213 fde *F = &fd_table[fd];
214 if (s)
215 xstrncpy(F->desc, s, FD_DESC_SZ);
216 else
217 *(F->desc) = 0; // ""-string
218}
219
220void
221fd_bytes(const int fd, const int len, const IoDirection direction)
222{
223 fde *F = &fd_table[fd];
224
225 if (len < 0)
226 return;
227
228 switch (direction) {
230 F->bytes_read += len;
231 break;
233 F->bytes_written += len;
234 break;
235 }
236}
237
238void
240{
241 int i;
242 fde *F;
243
244 for (i = 0; i < Squid_MaxFD; ++i) {
245 F = &fd_table[i];
246
247 if (!F->flags.open)
248 continue;
249
250 if (i == fileno(DebugStream()))
251 continue;
252
253 debugs(51, Important(17), "Open FD "<< std::left<< std::setw(10) <<
254 (F->bytes_read && F->bytes_written ? "READ/WRITE" :
255 F->bytes_read ? "READING" : F->bytes_written ? "WRITING" :
256 "UNSTARTED") <<
257 " "<< std::right << std::setw(4) << i << " " << F->desc);
258 }
259}
260
261int
263{
265}
266
267int
269{
270 int nrfree = fdNFree();
271
272 if (nrfree < (RESERVED_FD << 1))
273 return 1;
274
275 if (nrfree < (Number_FD >> 2))
276 return 1;
277
278 return 0;
279}
280
281/* Called when we runs out of file descriptors */
282void
284{
285 int newReserve;
286 int x;
287 static time_t last = 0;
288 /*
289 * don't update too frequently
290 */
291
292 if (last + 5 > squid_curtime)
293 return;
294
295 /*
296 * Calculate a new reserve, based on current usage and a small extra
297 */
298 newReserve = Squid_MaxFD - Number_FD + min(25, Squid_MaxFD / 16);
299
300 if (newReserve <= RESERVED_FD)
301 return;
302
303 x = Squid_MaxFD - 20 - min(25, Squid_MaxFD / 16);
304
305 if (newReserve > x) {
306 /* perhaps this should be fatal()? -DW */
307 debugs(51, DBG_CRITICAL, "WARNING: This machine has a serious shortage of filedescriptors.");
308 newReserve = x;
309 }
310
311 if (Squid_MaxFD - newReserve < min(256, Squid_MaxFD / 2))
312 fatalf("Too few filedescriptors available in the system (%d usable of %d).\n", Squid_MaxFD - newReserve, Squid_MaxFD);
313
314 debugs(51, DBG_CRITICAL, "Reserved FD adjusted from " << RESERVED_FD << " to " << newReserve <<
315 " due to failures (" << (Squid_MaxFD - newReserve) << "/" << Squid_MaxFD << " file descriptors available)");
316 RESERVED_FD = newReserve;
317}
318
time_t squid_curtime
#define assert(EX)
Definition assert.h:17
Definition fde.h:52
unsigned epoll_state
Definition fde.h:146
unsigned int type
Definition fde.h:105
char desc[FD_DESC_SZ]
Definition fde.h:115
int64_t bytes_written
Definition fde.h:135
PF * read_handler
Definition fde.h:149
struct fde::_fde_flags flags
void setIo(READ_HANDLER *, WRITE_HANDLER *)
set I/O methods for a freshly opened descriptor
Definition fde.cc:22
void clear()
Clear the fde class back to NULL equivalent.
Definition fde.h:72
PF * write_handler
Definition fde.h:151
int64_t bytes_read
Definition fde.h:134
A const & min(A const &lhs, A const &rhs)
#define Important(id)
Definition Messages.h:93
#define DBG_IMPORTANT
Definition Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
#define DBG_CRITICAL
Definition Stream.h:37
#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
void fatalf(const char *fmt,...)
Definition fatal.cc:68
int default_read_method(int, char *, int)
Definition fd.cc:124
void fd_close(int fd)
Definition fd.cc:76
void fd_note(int fd, const char *s)
Definition fd.cc:211
int fdNFree(void)
Definition fd.cc:262
const char * fdTypeStr[]
Definition fd.cc:34
int msghdr_read_method(int, char *, int)
Definition fd.cc:136
int default_write_method(int, const char *, int)
Definition fd.cc:130
void fdAdjustReserved(void)
Definition fd.cc:283
void fd_open(int fd, unsigned int type, const char *desc)
Definition fd.cc:151
static void fdUpdateBiggest(int fd, int)
Definition fd.cc:47
void fd_bytes(const int fd, const int len, const IoDirection direction)
Definition fd.cc:221
void fdDumpOpen(void)
Definition fd.cc:239
int fdUsageHigh(void)
Definition fd.cc:268
int msghdr_write_method(int, const char *, int)
Definition fd.cc:142
IoDirection
distinguishes reading/importing I/O operations from their writing/exporting counterparts
Definition fd.h:15
#define fd_table
Definition fde.h:189
int Opening_FD
int Squid_MaxFD
int Number_FD
int RESERVED_FD
int Biggest_FD
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
ssize_t xrecv(int socketFd, void *buf, size_t bufLength, int flags)
POSIX recv(2) equivalent.
Definition socket.h:98
ssize_t xsend(int socketFd, const void *buf, size_t bufLength, int flags)
POSIX send(2) equivalent.
Definition socket.h:110
#define MSG_NOSIGNAL
Definition socket.h:56
FILE * DebugStream()
Definition debug.cc:355
bool open
Definition fde.h:118
Definition cmsg.h:88
int xread(int fd, void *buf, size_t bufSize)
POSIX read(2) equivalent.
Definition unistd.h:61
int xwrite(int fd, const void *buf, size_t bufSize)
POSIX write(2) equivalent.
Definition unistd.h:67
char * xstrncpy(char *dst, const char *src, size_t n)
Definition xstring.cc:37