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