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"
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 
27 int default_read_method(int, char *, int);
28 int default_write_method(int, const char *, int);
29 #if _SQUID_WINDOWS_
30 int socket_read_method(int, char *, int);
31 int socket_write_method(int, const char *, int);
32 int file_read_method(int, char *, int);
33 int file_write_method(int, const char *, int);
34 #else
35 int msghdr_read_method(int, char *, int);
36 int msghdr_write_method(int, const char *, int);
37 #endif
38 
39 const char *fdTypeStr[] = {
40  "None",
41  "Log",
42  "File",
43  "Socket",
44  "Pipe",
45  "MsgHdr",
46  "Unknown"
47 };
48 
49 static void fdUpdateBiggest(int fd, int);
50 
51 static void
52 fdUpdateBiggest(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 
80 void
81 fd_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 == NULL);
90  assert(F->write_handler == NULL);
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 
103 int
104 socket_read_method(int fd, char *buf, int len)
105 {
106  return recv(fd, (void *) buf, len, 0);
107 }
108 
109 int
110 file_read_method(int fd, char *buf, int len)
111 {
112  return _read(fd, buf, len);
113 }
114 
115 int
116 socket_write_method(int fd, const char *buf, int len)
117 {
118  return send(fd, (const void *) buf, len, 0);
119 }
120 
121 int
122 file_write_method(int fd, const char *buf, int len)
123 {
124  return _write(fd, buf, len);
125 }
126 
127 #else
128 int
129 default_read_method(int fd, char *buf, int len)
130 {
131  return read(fd, buf, len);
132 }
133 
134 int
135 default_write_method(int fd, const char *buf, int len)
136 {
137  return write(fd, buf, len);
138 }
139 
140 int
141 msghdr_read_method(int fd, char *buf, int)
142 {
143  return recvmsg(fd, reinterpret_cast<msghdr*>(buf), MSG_DONTWAIT);
144 }
145 
146 int
147 msghdr_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 
155 void
156 fd_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 
215 void
216 fd_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 
225 void
226 fd_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 
241 void
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 
264 int
265 fdNFree(void)
266 {
267  return Squid_MaxFD - Number_FD - Opening_FD;
268 }
269 
270 int
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 */
285 void
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 
#define FD_DESC_SZ
Definition: defines.h:32
static void fdUpdateBiggest(int fd, int)
Definition: fd.cc:52
#define DBG_CRITICAL
Definition: Stream.h:40
void fd_note(int fd, const char *s)
Definition: fd.cc:216
int fdUsageHigh(void)
Definition: fd.cc:271
@ FD_SOCKET
Definition: enums.h:16
int Opening_FD
static uint32 F(uint32 X, uint32 Y, uint32 Z)
Definition: md4.c:46
@ FD_LOG
Definition: enums.h:14
int type
Definition: errorpage.cc:152
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
static char last
Definition: parse.c:451
Definition: fde.h:52
int msghdr_write_method(int, const char *, int)
Definition: fd.cc:147
#define NULL
Definition: types.h:166
void fdDumpOpen(void)
Definition: fd.cc:242
int default_read_method(int, char *, int)
Definition: fd.cc:129
#define assert(EX)
Definition: assert.h:19
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
int default_write_method(int, const char *, int)
Definition: fd.cc:135
time_t squid_curtime
Definition: stub_libtime.cc:20
void fdAdjustReserved(void)
Definition: fd.cc:286
int Squid_MaxFD
#define debug_log
change-avoidance macro; new code should call DebugStream() instead
Definition: Stream.h:185
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:226
void ResetSelect(int fd)
reset/undo/unregister the watch for an FD which was set by Comm::SetSelect()
Definition: Loops.h:30
#define fd_table
Definition: fde.h:189
int msghdr_read_method(int, char *, int)
Definition: fd.cc:141
@ FD_READ
Definition: enums.h:23
Definition: cmsg.h:88
#define MSG_NOSIGNAL
Definition: fd.cc:24
int fdNFree(void)
Definition: fd.cc:265
int RESERVED_FD
#define Important(id)
Definition: Messages.h:91
void fd_open(int fd, unsigned int type, const char *desc)
Definition: fd.cc:156
#define DBG_IMPORTANT
Definition: Stream.h:41
@ FD_MSGHDR
Definition: enums.h:18
@ FD_PIPE
Definition: enums.h:17
@ FD_WRITE
Definition: enums.h:24
void fd_close(int fd)
Definition: fd.cc:81
const char * fdTypeStr[]
Definition: fd.cc:39
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
int Number_FD
@ FD_FILE
Definition: enums.h:15
int Biggest_FD

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors